home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / src / htmlamiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  102.0 KB  |  3,734 lines

  1. /********************************************************************
  2.  
  3. Amiga specific code for controlling the gadget, etc.
  4.  
  5. *********************************************************************/
  6. /* We really don't need _all_ these... try to narrow it down some time */
  7.  
  8.  
  9. #include "includes.h"
  10. #include "HTML.h"
  11. #include "mosaic.h"
  12. #include "globals.h"
  13. #include "gui.h"
  14. #include "XtoI.h"
  15. #include "HTMLP.h"
  16. #include "HTMLImgMacro.h"
  17. #include "htmlgad.h"    /* defines for attributes */
  18. #include "NewGroup.h"
  19. #include "TextEditField.h"
  20. #include "protos.h"
  21.  
  22. extern struct IntuitionBase *IntuitionBase ;
  23. extern struct GfxBase *GfxBase;
  24. extern char *cached_url;
  25. extern int lib_version;
  26.  
  27. /* local functions */
  28.  
  29. ULONG dispatchHTMLGad(Class *, Object *, Msg);
  30. ULONG RenderHTMLGad(Class *, struct Gadget *, struct gpRender *);
  31. struct Region *installClipRegion(struct Window *, struct Layer *,
  32.                  struct Region *);
  33. void NotifyChange(Class *, Object *, struct gpInput *, Tag,ULONG);
  34. void HTML_reset_search(Widget);
  35. void new_button_press(HTMLGadClData *HTML_Data,long x,long y);
  36. void new_button_release(HTMLGadClData *HTML_Data,Object *obj,long x,long y);
  37. void ImageSubmitForm(FormInfo *,char *,int,int);
  38.  
  39. #ifdef ZZ
  40.  
  41. int FormatAll(HTMLPart *, int);
  42. char *ParseTextToString(struct ele_rec *, struct ele_rec *, struct ele_rec *,
  43.             int, int, int, int);
  44. HTMLSetText(HTMLGadClData *, char *, char *, char *, int, char *, void *);
  45. int DocumentWidth(HTMLGadClData *, struct mark_up *);
  46.  
  47.  
  48. extern ImageInfo *NoImageData(HTMLGadClData *);
  49. extern void TextRefresh(HTMLGadClData *, struct ele_rec *, int, int);
  50. extern void ImageRefresh(HTMLGadClData *, struct ele_rec *);
  51. extern int SwapElements(struct ele_rec *, struct ele_rec *, int, int);
  52. extern struct ref_rec *AddHRef(struct ref_rec *, char *);
  53. #endif
  54.  
  55. extern struct mark_up *HTMLParse(struct mark_up *, char *);
  56. extern int DocumentWidth(HTMLGadClData *, struct mark_up *);
  57. extern void ReformatWindow(HTMLGadClData *);
  58. extern void ScrollToPos(HTMLGadClData *, int, int);
  59. extern void ViewClearAndRefresh(HTMLGadClData *);
  60. extern struct ele_rec *LocateElement(HTMLGadClData *, int, int, int *);
  61. extern void SetAnchor(HTMLGadClData *);
  62. extern int IsDelayedHRef(HTMLGadClData *, char *);
  63. extern int AnchoredHeight(HTMLGadClData *);
  64. extern void UnsetAnchor(HTMLGadClData *);
  65. extern void ImageSubmitForm();
  66. extern long IsIsMapForm(HTMLGadClData *,char *);
  67.  
  68.  
  69. #define DEBUG0 0 /* Debug the forms/virtual group handlin */
  70. #define DEBUG1 0 /* Debug the image decoding */
  71. #define DEBUG2 0 /* Debug the forms handling */
  72.  
  73. ULONG __saveds __asm LayoutFunc(register __a0 struct Hook *h,register __a2 Object *obj,register __a1 struct MUI_LayoutMsg *lm);
  74.  
  75. ULONG __saveds __asm ScrollHookFunc(register __a0 struct Hook *hook,
  76.                register __a2 APTR          object,
  77.                register __a1 struct ScrollHookMsg *msg);
  78. extern ULONG HookEntry();
  79. extern mo_window window;
  80.  
  81. extern char *DBGstr; /* mjw*/
  82.  
  83. extern AppData Rdata;
  84.  
  85. /* Some compactness typedefs */
  86. typedef struct opSet * opSetP;
  87. typedef struct opGet * opGetP;
  88. typedef struct TextFont * TextFontP;
  89.  
  90. /************ MISC *************/
  91.  
  92. #define mui_version (MUIMasterBase->lib_Version)
  93. #define mui_add(x) (mui_version < 11 ? (x) : 0)
  94.  
  95.  
  96. #define IEQUALIFIER_SHIFT (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  97. #define IEQUALIFIER_ALT (IEQUALIFIER_LALT | IEQUALIFIER_RALT)
  98.  
  99. #define HIKEY_SHIFT    (0x100)
  100. #define HIKEY_ALT    (0x200)
  101. #define HIKEY_CTRL    (0x400)
  102.  
  103. #define MUIA_FillArea 0x804294A3 /* V4 BOOL (private) */
  104. #define MUIV_Listview_MultiSelect_Def 1
  105.  
  106. /********* CLASS HANDLING *************/
  107.  
  108. __asm ULONG HTMLGadClDispatch(register __a0 Class *cl,
  109.                   register __a2 Object *obj,
  110.                  register __a1 Msg msg);
  111.  
  112. __asm ULONG HTMLTextClDispatch(register __a0 Class *cl,
  113.                   register __a2 Object *obj,
  114.                  register __a1 Msg msg);
  115.  
  116. __asm ULONG HTMLTextNClDispatch(register __a0 Class *cl,
  117.                   register __a2 Object *obj,
  118.                  register __a1 Msg msg);
  119.  
  120. /************************************************************
  121.   Initilize the new HTML MUI Gadget Class (was initHTMLGadClass)
  122. ************************************************************/
  123. struct MUI_CustomClass *HTMLText;
  124. struct MUI_CustomClass *HTMLTextN;
  125. struct Hook ScrollHook;
  126. struct Hook FormButton_hook;
  127. struct Hook FormString_hook;
  128. struct Hook FormRadio_hook;
  129. struct Hook TextEdit_hook;
  130. static struct Hook LayoutHook = { {0,0}, LayoutFunc, NULL, NULL };
  131.  
  132. struct MUI_CustomClass *HTMLGadClInit(void)
  133. {
  134.     struct MUI_CustomClass *cl;
  135.  
  136.     /* Create the HTML gadget class */
  137.     if (!(cl = MUI_CreateCustomClass(NULL,MUIC_Group,NULL,
  138.                         sizeof(HTMLGadClData),(APTR)HTMLGadClDispatch)))
  139.         fail(NULL, "Failed to create HTMLGad class."); /* Failed, cleanup */
  140.  
  141.     if (!(HTMLText = MUI_CreateCustomClass(NULL,MUIC_Area,NULL,
  142.                         sizeof(HTMLTextClData),(APTR)HTMLTextClDispatch)))
  143.         fail(NULL, "Failed to create HTMLText class."); /* Failed, cleanup */
  144.  
  145.     if (!(HTMLTextN = MUI_CreateCustomClass(NULL,MUIC_Area,NULL,
  146.                         sizeof(HTMLTextNClData),(APTR)HTMLTextNClDispatch)))
  147.         fail(NULL, "Failed to create HTMLTextN class."); /* Failed, cleanup */
  148.  
  149.   return cl;
  150. }
  151.  
  152. /*******************************************************
  153.   Free our MUI HTML Gadget Class
  154. *******************************************************/
  155. BOOL HTMLGadClFree(struct MUI_CustomClass *mcc)
  156. {
  157.     MUI_DeleteCustomClass(HTMLText);
  158.     MUI_DeleteCustomClass(HTMLTextN);
  159.     MUI_DeleteCustomClass(mcc);
  160.     return 0;
  161. }
  162.  
  163. ULONG __stdargs DoSuperNew(struct IClass *cl,Object *obj,ULONG tag1,...)
  164. {
  165.     return(DoSuperMethod(cl,obj,OM_NEW,&tag1,NULL));
  166. }
  167.  
  168. /*************** INSTANCE HANDLING (METHODS) *************/
  169. /*
  170. ** AskMinMax method will be called before the window is opened
  171. ** and before layout takes place. We need to tell MUI the
  172. ** minimum, maximum and default size of our object.
  173. */
  174.  
  175. static ULONG HTMLGadClAskMinMax(Class *cl, Object *obj, struct MUIP_AskMinMax *msg){
  176.   /*
  177.    ** let our superclass first fill in what it thinks about sizes.
  178.    ** this will e.g. add the size of frame and inner spacing.
  179.    */
  180.   DoSuperMethodA(cl,obj,(Msg)msg);
  181.   /*
  182.    ** now add the values specific to our object. note that we
  183.    ** indeed need to *add* these values, not just set them!
  184.    */
  185.   
  186. #ifndef _HTMLFORMS
  187.   msg->MinMaxInfo->MinWidth  += 100;
  188.   msg->MinMaxInfo->DefWidth  += 300;
  189.   msg->MinMaxInfo->MaxWidth  += 1000;  /* There is an unlimited val, use it*/
  190.  
  191.   msg->MinMaxInfo->MinHeight += 50;
  192.   msg->MinMaxInfo->DefHeight += 350;
  193.   msg->MinMaxInfo->MaxHeight += 1000; /* same here */
  194. #endif
  195.   return(0);
  196. }
  197.  
  198. static ULONG HTMLGadClNew(Class *cl, Object *obj,struct opSet *msg){
  199. /* CHECK LAST PARAM */
  200.    
  201.     HTMLGadClData *inst; 
  202.  
  203.     if (!(obj= (Object *)DoSuperNew(cl,obj,
  204.                 MUIA_Group_PageMode,TRUE,
  205.                 MUIA_Group_ActivePage,0,
  206.                 MUIA_FillArea,FALSE, /* I am handling the background */
  207.                         /* If it is a normal page */
  208.                 Child,G_Norm = NewObject(HTMLTextN->mcc_Class,NULL,MUIA_FillArea,FALSE,TAG_DONE),
  209.                         /* If it is a page with forms */
  210.                 Child,G_Virt=VirtgroupObject,
  211.                     NoFrame,
  212. //                    MUIA_FillArea,FALSE,
  213.                     MUIA_Background,MUII_BACKGROUND,
  214.                     Child,G_Forms=NewObject(HTMLText->mcc_Class,NULL,MUIA_Background,MUII_BACKGROUND,FALSE,TAG_DONE),
  215.                     MUIA_Group_LayoutHook, &LayoutHook,
  216.                     End,
  217.                 TAG_MORE,msg->ops_AttrList)))
  218.         return 0L;
  219.  
  220.     inst = INST_DATA(cl, obj);
  221.  
  222.     set(G_Forms,HTMLA_HTML_Data,inst); /* Make sure that the text class */
  223.     set(G_Norm,HTMLA_HTML_Data,inst);  /*  knows about the text */
  224.  
  225.  
  226.     inst->have_forms=0;
  227.   
  228.   inst->margin_width = 6;
  229.   inst->margin_height = 4;
  230.   inst->foreground = 1;
  231.   inst->anchor_fg = 3;
  232.   inst->visitedAnchor_fg = 1;
  233.   inst->activeAnchor_bg = 0;
  234.   inst->activeAnchor_fg = 2;
  235.   inst->num_anchor_underlines = 1;
  236.   inst->num_visitedAnchor_underlines = 1;
  237.   inst->dashed_anchor_lines = FALSE;
  238.   inst->dashed_visitedAnchor_lines = TRUE;
  239.   inst->border_images = FALSE;
  240.   inst->delay_images = TRUE;
  241.   inst->is_index = FALSE;
  242.   inst->percent_vert_space = 0;
  243.   
  244.   inst->raw_text = (char *)GetTagData(HTMLA_raw_text, NULL,
  245.                       ((opSetP)msg)->ops_AttrList);
  246.   inst->font = (TextFontP)GetTagData(HTMLA_font, NULL,
  247.                      ((opSetP)msg)->ops_AttrList);
  248.   inst->italic_font = (TextFontP)GetTagData(HTMLA_italic_font, NULL,
  249.                         ((opSetP)msg)->ops_AttrList);
  250.   inst->bold_font = (TextFontP)GetTagData(HTMLA_bold_font, NULL,
  251.                       ((opSetP)msg)->ops_AttrList);
  252.   inst->fixed_font = (TextFontP)GetTagData(HTMLA_fixed_font, NULL,
  253.                        ((opSetP)msg)->ops_AttrList);
  254.   inst->header1_font = (TextFontP)GetTagData(HTMLA_header1_font, NULL,
  255.                          ((opSetP)msg)->ops_AttrList);
  256.   inst->header2_font = (TextFontP)GetTagData(HTMLA_header2_font, NULL,
  257.                          ((opSetP)msg)->ops_AttrList);
  258.   inst->header3_font = (TextFontP)GetTagData(HTMLA_header3_font, NULL,
  259.                          ((opSetP)msg)->ops_AttrList);
  260.   inst->header4_font = (TextFontP)GetTagData(HTMLA_header4_font, NULL,
  261.                          ((opSetP)msg)->ops_AttrList);
  262.   inst->header5_font = (TextFontP)GetTagData(HTMLA_header5_font, NULL,
  263.                          ((opSetP)msg)->ops_AttrList);
  264.   inst->header6_font = (TextFontP)GetTagData(HTMLA_header6_font, NULL,
  265.                          ((opSetP)msg)->ops_AttrList);
  266.   inst->address_font = (TextFontP)GetTagData(HTMLA_address_font, NULL,
  267.                          ((opSetP)msg)->ops_AttrList);
  268.   inst->plain_font = (TextFontP)GetTagData(HTMLA_plain_font, NULL,
  269.                        ((opSetP)msg)->ops_AttrList);
  270.   inst->listing_font = (TextFontP)GetTagData(HTMLA_listing_font, NULL,
  271.                          ((opSetP)msg)->ops_AttrList);
  272.   inst->previously_visited_test =
  273.    (visitTestProc)GetTagData(HTMLA_visit_func, NULL,
  274.                  ((opSetP)msg)->ops_AttrList);
  275.   inst->resolveImage =
  276.    (resolveImageProc)GetTagData(HTMLA_image_func, NULL,
  277.                 ((opSetP)msg)->ops_AttrList);
  278.  
  279.     inst->keyctrl = GetTagData(HTMLA_ScrollKeys, TRUE,
  280.                          ((opSetP)msg)->ops_AttrList);
  281.   
  282.   inst->scroll_x = 0;
  283.   inst->scroll_y = 0;
  284.   inst->use_vbar = TRUE;
  285.   inst->use_hbar = TRUE;
  286.   
  287.   inst->html_objects = HTMLParse(NULL, inst->raw_text);
  288.   inst->html_header_objects = HTMLParse(NULL, inst->header_text);
  289.   inst->html_footer_objects = HTMLParse(NULL, inst->footer_text);
  290.   inst->formatted_elements = NULL;
  291.   inst->my_visited_hrefs = NULL;
  292.   inst->my_delayed_images = NULL;
  293.     inst->widget_list = NULL;
  294.   inst->form_list = NULL;
  295.   inst->line_array = NULL;
  296.   inst->line_count = 0;
  297.   inst->max_pre_width = DocumentWidth(inst, inst->html_objects);
  298.   inst->doc_width = inst->max_pre_width;
  299.   inst->select_start = NULL;
  300.   inst->select_end = NULL;
  301.   inst->sel_start_pos = 0;
  302.   inst->sel_end_pos = 0;
  303.   inst->new_start = NULL;
  304.   inst->new_end = NULL;
  305.   inst->new_start_pos = 0;
  306.   inst->new_end_pos = 0;
  307.   inst->active_anchor = NULL;
  308.   inst->cached_tracked_ele = NULL;
  309.   inst->inlined_image_to_load = NULL;
  310.   inst->active = TRUE;
  311.  
  312.   inst->reparsing=0;
  313.  
  314.   return (ULONG)obj;
  315. }
  316.  
  317. static ULONG HTMLGadClDispose(Class *cl, Object *obj, Msg msg){
  318.     return(DoSuperMethodA(cl,obj,msg));
  319. }
  320.  
  321. #define C24C3_32(x) (((x&0xFF0000)<<8)|((x&0xFF0000))|((x&0xFF0000)>>8)|((x&0xFF0000)>>16)),\
  322. (((x&0xFF00)<<16)|((x&0xFF00)<<8)|((x&0xFF00))|((x&0xFF00)>>8)),\
  323. (((x&0xFF)<<24)|((x&0xFF)<<16)|((x&0xFF)<<8)|((x&0xFF)))
  324.  
  325. static ULONG HTMLGadClSetup(Class *cl, Object *obj, Msg msg){
  326.     HTMLGadClData *inst=INST_DATA(cl,obj);
  327.     long col;
  328.  
  329.     if (!DoSuperMethodA(cl,obj,msg))
  330.         return FALSE;
  331.  
  332.   /* Allow input to gadget */
  333. //  MUI_RequestIDCMP(obj, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY);
  334.  
  335.     col = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,C24C3_32(Rdata.u_anchor),
  336.                 OBP_Precision, PRECISION_IMAGE, TAG_DONE);
  337.     if(col!=-1)
  338.         inst->anchor_fg=col;
  339.     else
  340.         inst->anchor_fg=1;
  341.     inst->anchor_fgc=col;
  342.  
  343. /*
  344. I mean: FollowedLink, same with UnfollowedLink and
  345.            ?ActiveLink
  346. */
  347.  
  348.     col = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,C24C3_32(Rdata.f_anchor),
  349.                 OBP_Precision, PRECISION_IMAGE, TAG_DONE);
  350.     if(col!=-1)
  351.         inst->visitedAnchor_fg=col;
  352.     else
  353.         inst->visitedAnchor_fg=1;
  354.     inst->visitedAnchor_fgc=col;
  355.  
  356.     col = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,C24C3_32(Rdata.a_anchor),
  357.                 OBP_Precision, PRECISION_IMAGE, TAG_DONE);
  358.     if(col!=-1)
  359.         inst->activeAnchor_fg=col;
  360.     else
  361.         inst->activeAnchor_fg=2;
  362.     inst->activeAnchor_fgc=col;
  363.  
  364.   return TRUE;
  365. }
  366.  
  367. static ULONG HTMLGadClCleanup( Class *cl, Object *obj, Msg msg){
  368.     HTMLGadClData *inst = INST_DATA(cl, obj);
  369. //    MUI_RejectIDCMP(obj,IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY); /* and more */
  370.  
  371. //    TO_HTML_FlushImageCache();
  372.     if(!inst->have_formsI){
  373.         mo_flush_image_cache(&window);
  374. //        kprintf("Flushing cache\n");
  375.         }
  376.  
  377.  
  378.     if(inst->anchor_fgc!=-1) ReleasePen(_screen(obj)->ViewPort.ColorMap, inst->anchor_fgc);
  379.     if(inst->visitedAnchor_fgc!=-1) ReleasePen(_screen(obj)->ViewPort.ColorMap, inst->visitedAnchor_fgc);
  380.     if(inst->activeAnchor_fgc!=-1) ReleasePen(_screen(obj)->ViewPort.ColorMap, inst->activeAnchor_fgc);
  381.  
  382.     return (DoSuperMethodA(cl,obj,msg));
  383. }  
  384.  
  385.  
  386. static ULONG HTMLGadClShow(Class *cl, Object *obj, Msg msg){
  387.     HTMLGadClData *inst; 
  388.  
  389.     DoSuperMethodA(cl,obj,msg);
  390.  
  391.     inst = INST_DATA(cl, obj);
  392.  
  393.     inst->view_left = _mleft(obj);
  394.     inst->view_top = _mtop(obj);
  395.     inst->view_width = _mwidth(obj);
  396.     inst->view_height = _mheight(obj);
  397.     inst->rp=_rp(obj);
  398.     inst->win=_window(obj);
  399.  
  400.     if(!inst->reparsing){
  401.         inst->object_flags|=Object_Reparsing;
  402.         if(!inst->have_forms)
  403.             ReformatWindow(inst);
  404.         SetAttrs(inst->SB_Vert,MUIA_Prop_Entries,inst->doc_height,
  405.                                 MUIA_Prop_Visible,_mheight(obj),TAG_DONE);
  406.         SetAttrs(inst->SB_Horiz,MUIA_Prop_Entries,inst->doc_width,
  407.                                 MUIA_Prop_Visible,_mwidth(obj),TAG_DONE);
  408.         inst->object_flags&=~Object_Reparsing;
  409.         }
  410.     return TRUE;
  411. }
  412.  
  413. static ULONG HTMLGadClHide(Class *cl, Object *obj, Msg msg){
  414.     HTMLGadClData *inst; 
  415.  
  416.     DoSuperMethodA(cl,obj,msg);
  417.  
  418.     inst = INST_DATA(cl, obj);
  419.  
  420. /*    inst->view_left        = -2242355;
  421.     inst->view_top        = 1425;
  422.     inst->view_width    = -23255;
  423.     inst->view_height    = 3453664; */
  424.     inst->rp            = NULL;
  425.     inst->win            = NULL;
  426.  
  427.     return TRUE;
  428. }
  429.  
  430. static ULONG HTMLGadClResetAmigaGadgets( Class *cl, Object *obj, Msg msg){
  431.  
  432.     HTMLGadClData *inst = INST_DATA(cl, obj);
  433.  
  434.     SetAttrs(inst->SB_Vert,MUIA_Prop_Entries,inst->doc_height,
  435.                             MUIA_Prop_Visible,_mheight(obj),TAG_DONE);
  436.  
  437.     SetAttrs(inst->SB_Horiz,MUIA_Prop_Entries,inst->doc_width,
  438.                             MUIA_Prop_Visible,_mwidth(obj),TAG_DONE);
  439.  
  440.     nnset(inst->SB_Vert,MUIA_Prop_First,inst->new_scroll_y);
  441.     nnset(inst->SB_Horiz,MUIA_Prop_First,0);
  442.  
  443.     set(HTML_Gad,HTMLA_Top,inst->new_scroll_y);
  444.     set(HTML_Gad,HTMLA_Left,0);
  445.  
  446.     if(!Rdata.isindex_to_form && inst->is_index)
  447.         set(PG_Bottom, MUIA_Group_ActivePage, 2); /* Search gadgets */
  448.     else
  449.         set(PG_Bottom, MUIA_Group_ActivePage, 0); /* Text gadget */
  450.  
  451. //  set(LV_Source, MUIA_Floattext_Text, t);
  452.  
  453.     return TRUE;
  454. }  
  455.  
  456. static ULONG HTMLGadClResetAmigaGadgetsNoScroll( Class *cl, Object *obj, Msg msg){
  457.  
  458.     HTMLGadClData *inst = INST_DATA(cl, obj);
  459.  
  460.     SetAttrs(inst->SB_Vert,MUIA_Prop_Entries,inst->doc_height,
  461.                             MUIA_Prop_Visible,_mheight(obj),TAG_DONE);
  462.  
  463.     SetAttrs(inst->SB_Horiz,MUIA_Prop_Entries,inst->doc_width,
  464.                             MUIA_Prop_Visible,_mwidth(obj),TAG_DONE);
  465.  
  466.     return TRUE;
  467. }  
  468.  
  469. static ULONG HTMLGadClResetTopLeft( Class *cl, Object *obj, Msg msg){
  470.  
  471.     HTMLGadClData *inst = INST_DATA(cl, obj);
  472.  
  473.     nnset(inst->SB_Vert,MUIA_Prop_First,0);
  474.     nnset(inst->SB_Horiz,MUIA_Prop_First,0);
  475.  
  476.     return TRUE;
  477. }  
  478.  
  479. static ULONG HTMLGadClGet(Class *cl, Object *obj, Msg msg){
  480.  
  481.   HTMLGadClData *inst = INST_DATA(cl, obj);
  482.   switch (((opGetP)msg)->opg_AttrID) {
  483.   case HTMLA_title:
  484.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->title);
  485.     break;
  486.     
  487.   case HTMLA_raw_text:
  488.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->raw_text);
  489.     break;
  490.     
  491.   case HTMLA_image_load:
  492.     *(((opGetP)msg)->opg_Storage) =
  493.      (ULONG)(inst->inlined_image_to_load);
  494.     break;
  495.     
  496.   case HTMLA_new_href:
  497.     *(((opGetP)msg)->opg_Storage) =
  498.      (ULONG)(inst->chosen_anchor);
  499.     /*
  500.        if ((IsDelayedHRef(inst, inst->chosen_anchor->anchorHRef)) ||
  501.        (inst->chosen_anchor->pic_data->delayed == 2)) {
  502.        *(((opGetP)msg)->opg_Storage) =
  503.        (ULONG)(inst->chosen_anchor->edata);
  504.        } else {
  505.        *(((opGetP)msg)->opg_Storage) =
  506.        (ULONG)(inst->chosen_anchor->anchorHRef);
  507.        }
  508.        */
  509.     break;
  510.   case HTMLA_post_text:
  511.     *(((opGetP)msg)->opg_Storage) = (ULONG)inst->post_text;
  512.     break;
  513.  
  514.   case HTMLA_post_href:
  515.     *(((opGetP)msg)->opg_Storage) = (ULONG)inst->post_href;
  516.     break;
  517.    
  518.   case HTMLA_get_href:
  519.     *(((opGetP)msg)->opg_Storage) = (ULONG)inst->post_href;
  520.     break;
  521.    
  522.   case HTMLA_doc_height:
  523.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->doc_height);
  524.     break;
  525.  
  526.   case HTMLA_view_height:
  527.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->view_height);
  528.     break;
  529.  
  530.   case HTMLA_doc_width:
  531.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->doc_width);
  532.     break;
  533.     
  534.   case HTMLA_view_width:
  535.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->view_width);
  536.     break;
  537.  
  538.   case HTMLA_anchor_fg:
  539.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->anchor_fg);
  540.     break;
  541.     
  542.   case HTMLA_visited_fg:
  543.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->visitedAnchor_fg);
  544.     break;
  545.     
  546.   case HTMLA_active_fg:
  547.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->activeAnchor_fg);
  548.     break;
  549.     
  550.   case HTMLA_inst:
  551.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst);
  552.     break;
  553.     
  554.   case HTMLA_scroll_y:
  555.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->scroll_y);
  556.     break;
  557.  
  558.   case HTMLA_Top:
  559.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->scroll_y);
  560.     break;
  561.   case HTMLA_Left:
  562.     *(((opGetP)msg)->opg_Storage) = (ULONG)(inst->scroll_x);
  563.     break;
  564.   }
  565.   
  566.   return DoSuperMethodA(cl, obj, msg);
  567. }
  568.  
  569. static ULONG HTMLGadClSet(Class *cl, Object *obj, Msg msg){
  570.     HTMLGadClData *inst = INST_DATA(cl, obj);
  571.     struct TagItem *tstate, *ti;
  572.     struct RastPort *rp;
  573.   
  574.     ti = ((opSetP)msg)->ops_AttrList;
  575.     tstate = ti;
  576.   
  577.     while (ti = NextTagItem(&tstate)) {
  578.     switch (ti->ti_Tag) {
  579.       
  580.     case HTMLA_active:        inst->active = ti->ti_Data; break;
  581.     case HTMLA_anchor_fg:    inst->anchor_fg = ti->ti_Data; break;
  582.     case HTMLA_visited_fg:    inst->visitedAnchor_fg = ti->ti_Data; break;
  583.     case HTMLA_active_fg:    inst->activeAnchor_fg = ti->ti_Data; break;
  584.     case HTMLA_new_href:    break; /* Is this right? Do nothing? */
  585.     case HTMLA_get_href:    inst->post_href=(char *)ti->ti_Data; break;
  586.     case HTMLA_post_text:    inst->post_text=(char *)ti->ti_Data; break;
  587.     case HTMLA_post_href:    inst->post_href=(char *)ti->ti_Data; break;
  588.     case HTMLA_ScrollKeys:    inst->keyctrl=ti->ti_Data; break;
  589.       
  590.     case HTMLA_raw_text:
  591.         rp = ObtainGIRPort(((opSetP)msg)->ops_GInfo);
  592.         if (inst->rp == NULL) 
  593.             inst->rp = rp;
  594.         if (rp) {
  595.             HTMLSetText(inst, (char *)ti->ti_Data, NULL, NULL, 0, NULL, NULL);
  596.             ReleaseGIRPort(rp);
  597.             }
  598.         else {
  599.             inst->raw_text = (char *)ti->ti_Data;
  600.             inst->html_objects = NULL;
  601.               }
  602.         break;
  603.       
  604.     case HTMLA_scroll_y:
  605. /* Take care of the virtual group here */
  606. /*        inst->new_scroll_value=ti->ti_Data;
  607.         inst->new_scroll_dir=0; */
  608.  
  609.  
  610. #if DEBUG0==1
  611.         kprintf("HTML Main gad: Getting a new Y position: %ld\n",ti->ti_Data);
  612. #endif
  613.         nnset(inst->SB_Vert,MUIA_Prop_First,ti->ti_Data);
  614.         if(inst->have_forms)
  615.             set(G_Forms,HTMLA_Top,ti->ti_Data);
  616.         else
  617.             set(G_Norm,HTMLA_Top,ti->ti_Data);
  618.         break;
  619.       
  620.     case HTMLA_scroll_x:
  621. /* Take care of the virtual group here */
  622. /*        inst->new_scroll_value=ti->ti_Data;
  623.         inst->new_scroll_dir=1; */
  624.  
  625. #if DEBUG0==1
  626.         kprintf("HTML Main gad: Getting a new X position: %ld\n",ti->ti_Data);
  627. #endif
  628.         nnset(inst->SB_Horiz,MUIA_Prop_First,ti->ti_Data);
  629.         if(inst->have_forms)
  630.             set(G_Forms,HTMLA_Left,ti->ti_Data);
  631.         else
  632.             set(G_Norm,HTMLA_Left,ti->ti_Data);
  633.  
  634.         break;
  635.     case HTMLA_image_load: inst->inlined_image_to_load=(char *)ti->ti_Data; break;
  636.     case HTMLA_SB_Vert:        inst->SB_Vert=(Object *)ti->ti_Data; break;
  637.     case HTMLA_SB_Horiz:    inst->SB_Horiz=(Object *)ti->ti_Data; break;
  638.     }
  639.   }
  640.   return DoSuperMethodA(cl, obj, msg);
  641. }
  642.  
  643. static HandleInput(struct MUIP_HandleInput *msg)
  644. {
  645.     HTMLGadClData *inst = INST_DATA(HTMLGadClass, HTML_Gad);
  646.     long data;
  647.     UWORD keycode;
  648.     Object *obj=HTML_Gad;
  649.  
  650.     if (msg->imsg) {
  651.         switch(msg->imsg->Class){
  652.  
  653.             case IDCMP_MOUSEBUTTONS:{
  654.                 switch (msg->imsg->Code){
  655.                     case SELECTDOWN:
  656.                         if((msg->imsg->MouseX>=_mleft(obj)) && (msg->imsg->MouseX<=_mright(obj)) &&
  657.                            (msg->imsg->MouseY>=_mtop(obj)) && (msg->imsg->MouseY<=_mbottom(obj))){
  658.                             new_button_press(inst,msg->imsg->MouseX-inst->view_left,msg->imsg->MouseY-inst->view_top);
  659.                             }
  660.                         break;
  661.                     case SELECTUP:        /* user let go of button */
  662.                         new_button_release(inst,obj,msg->imsg->MouseX-inst->view_left,msg->imsg->MouseY-inst->view_top);
  663.                         break;
  664.                     }
  665.                 }
  666.                 break;
  667.  
  668.             case IDCMP_MOUSEMOVE: {
  669.                 char *href, *old;
  670.                 struct ele_rec *eptr;
  671.                 int epos;
  672.                 if (Rdata.track_pointer_motion && inst->active) {
  673.                     if((msg->imsg->MouseX>=_mleft(obj)) && (msg->imsg->MouseX<=_mright(obj)) &&
  674.                        (msg->imsg->MouseY>=_mtop(obj)) && (msg->imsg->MouseY<=_mbottom(obj))){
  675.  
  676.                         eptr = LocateElement(inst, _window(obj)->MouseX - inst->view_left,
  677.                                     _window(obj)->MouseY - inst->view_top, &epos);
  678.                         if (eptr && eptr->anchorHRef) {
  679.                             if (!strncmp(eptr->anchorHRef, "Delayed Image", 13))
  680.                                 href = strdup(eptr->edata);    /* get the real URL name */
  681.                             else
  682.                                 href = strdup(eptr->anchorHRef);
  683.                         href = mo_url_canonicalize_keep_anchor(href, window.cached_url);
  684.                         mo_convert_newlines_to_spaces(href);
  685.                         }
  686.                     else {
  687.                         href = strdup("");
  688.                         }
  689.                 }
  690.                 else href = strdup("");
  691.  
  692.                 get(TX_Dest, MUIA_Text_Contents, &old);
  693.                 if ((!old) || (old && strcmp(old, href))) /* to minimize flashing */
  694.                     set(TX_Dest, MUIA_Text_Contents, href);
  695.                 free(href);
  696.                 }
  697.             }
  698.                 break;
  699.  
  700.             case IDCMP_RAWKEY:
  701.                 if(inst->keyctrl){
  702.                     keycode=msg->imsg->Code;
  703.                     if(msg->imsg->Qualifier & IEQUALIFIER_SHIFT)
  704.                         keycode |= HIKEY_SHIFT;
  705.                     if(msg->imsg->Qualifier & IEQUALIFIER_ALT)
  706.                         keycode |= HIKEY_ALT;
  707.                     if(msg->imsg->Qualifier & IEQUALIFIER_CONTROL)
  708.                         keycode |= HIKEY_CTRL;
  709.                     switch (keycode){
  710.                         case 0x3E: /* Keypad 8 (up) */
  711.                         case CURSORUP:
  712.                              get(inst->SB_Vert, MUIA_Prop_First, &data);
  713.                             set(inst->SB_Vert, MUIA_Prop_First, data-10);
  714.                             break;
  715.  
  716.                         case 0x1E: /* Keypad 2 (down) */
  717.                         case CURSORDOWN:
  718.                              get(inst->SB_Vert, MUIA_Prop_First, &data);
  719.                             set(inst->SB_Vert, MUIA_Prop_First, data+10);
  720.                             break;
  721.  
  722.                         case 0x2D: /* Keypad 4 (left) */
  723.                         case CURSORLEFT:
  724.                              get(inst->SB_Horiz, MUIA_Prop_First, &data);
  725.                             set(inst->SB_Horiz, MUIA_Prop_First, data-10);
  726.                             break;
  727.  
  728.                         case 0x2F: /* Keypad 6 (right) */
  729.                         case CURSORRIGHT:
  730.                              get(inst->SB_Horiz, MUIA_Prop_First, &data);
  731.                             set(inst->SB_Horiz, MUIA_Prop_First, data+10);
  732.                             break;
  733.  
  734.                         case 0x1F: /* Keypad 3 (PgDn) */
  735.                         case (0x1E | HIKEY_SHIFT): /* Shift Keypad 2 (down) */
  736.                         case (CURSORDOWN | HIKEY_SHIFT):
  737.                         case 0x40: /* Space */
  738.                              get(inst->SB_Vert, MUIA_Prop_First, &data);
  739.                             set(inst->SB_Vert, MUIA_Prop_First, data+((_mheight(obj)*3)>>2));
  740.                             break;
  741.  
  742.                         case 0x3F: /* Keypad 9 (PgUp) */
  743.                         case (0x3E | HIKEY_SHIFT): /* Shift Keypad 8 (up) */
  744.                         case (CURSORUP | HIKEY_SHIFT):
  745.                         case 0x41: /* Backspace */
  746.                              get(inst->SB_Vert, MUIA_Prop_First, &data);
  747.                             set(inst->SB_Vert, MUIA_Prop_First, data-((_mheight(obj)*3)>>2));
  748.                             break;
  749.  
  750.                         case (CURSORLEFT | HIKEY_SHIFT):
  751.                         case (0x2D | HIKEY_SHIFT): /* Shift Keypad 4 (left) */
  752.                              get(inst->SB_Horiz, MUIA_Prop_First, &data);
  753.                             set(inst->SB_Horiz, MUIA_Prop_First, data-((_mwidth(obj)*3)>>2));
  754.                             break;
  755.  
  756.                         case (0x2F | HIKEY_SHIFT): /* Shift Keypad 6 (right) */
  757.                         case (CURSORRIGHT | HIKEY_SHIFT):
  758.                              get(inst->SB_Horiz, MUIA_Prop_First, &data);
  759.                             set(inst->SB_Horiz, MUIA_Prop_First, data+((_mwidth(obj)*3)>>2));
  760.                             break;
  761.  
  762.                         case 0x3D: /* Keypad 7 (Home) */
  763.                         case (0x3E | HIKEY_CTRL): /* Ctrl Keypad 8 (up) */
  764.                         case (CURSORUP | HIKEY_CTRL):
  765.                             set(inst->SB_Vert, MUIA_Prop_First,0); /* Beg of file */
  766.                             break;
  767.  
  768.                         case 0x1D: /* Keypad 1 (End) */
  769.                         case (0x1E | HIKEY_CTRL): /* Ctrl Keypad 2 (down) */
  770.                         case (CURSORDOWN | HIKEY_CTRL):
  771.                             set(inst->SB_Vert, MUIA_Prop_First,inst->doc_height-_mheight(obj)); /* End of file */
  772.                             break;
  773.  
  774.                         case (0x2D | HIKEY_CTRL): /* Ctrl Keypad 4 (left) */
  775.                         case (CURSORLEFT | HIKEY_CTRL):
  776.                             set(inst->SB_Horiz, MUIA_Prop_First,0); /* Beg of file */
  777.                             break;
  778.  
  779.                         case (0x2F | HIKEY_CTRL): /* Ctrl Keypad 6 (right) */
  780.                         case (CURSORRIGHT | HIKEY_CTRL):
  781.                             set(inst->SB_Horiz, MUIA_Prop_First,inst->doc_width-_mwidth(obj)); /* End of file */
  782.                             break;
  783.                         }
  784.                     }
  785.                 break;
  786.             }
  787.       }
  788.     return 0;
  789. }
  790.  
  791.  
  792. /*------------------------------------------------------------------------
  793.   Draw the HTML Gadget
  794.   ------------------------------------------------------------------------*/
  795. static ULONG HTMLGadClDraw(Class *cl, Object *obj, struct MUIP_Draw *msg){
  796.     HTMLGadClData *HTML_Data = INST_DATA(cl, obj);
  797.  
  798.     DoSuperMethodA(cl,obj,(Msg)msg);
  799.  
  800. //    if(!(msg->flags & MADF_DRAWOBJECT) && !(msg->flags & MADF_DRAWUPDATE))
  801. //        return 0L;
  802.  
  803. //    if(msg->flags & MADF_DRAWUPDATE) /* scroll to position */
  804. //        ScrollToPos(HTML_Data, HTML_Data->new_scroll_dir, HTML_Data->new_scroll_value);
  805.  
  806. //    if(msg->flags & MADF_DRAWOBJECT) /* total redraw */
  807. //        {
  808. //        /* This is necessary in case the HTMLSetText was called before the gadget
  809. //           was ready, i.e. after a window resize.  This is MUI's fault (still!) */
  810. //  
  811. //        if (HTML_Data->html_objects == NULL) {
  812. //    NotifyChange(cl, (Object *)g, (struct gpInput *)msg, HTML_mui_resize, (ULONG)NULL);
  813. //            ResetAmigaGadgets(); /* Hope this is correct */
  814. //            HTMLSetText(HTML_Data, HTML_Data->raw_text, NULL, NULL, 0, NULL, NULL);
  815. //             }
  816.  
  817. /*  ReformatWindow(HTML_Data); */ /* This is done in show */
  818. //    ViewClearAndRefresh(HTML_Data);
  819. //        }
  820. //    DoSuperMethodA(cl,obj,(Msg)msg);
  821.  
  822.     return 0;
  823. }
  824.  
  825. __saveds ULONG HTMLGadClPlaceObject(struct IClass *cl,Object *obj,struct MUIP_PlaceObject *msg)
  826. {
  827.     HTMLGadClData *inst = INST_DATA(cl, obj);
  828.  
  829.     if(MUIMasterBase->lib_Version<11){
  830.         if(inst->have_forms){
  831. //            kprintf("Custom layout\n");
  832.             inst->view_left = _mleft(HTML_Gad);
  833.             inst->view_top = _mtop(HTML_Gad);
  834.             inst->view_width = _mwidth(HTML_Gad);
  835.             inst->view_height = _mheight(HTML_Gad);
  836.             inst->rp=_rp(HTML_Gad);
  837.             inst->win=_window(HTML_Gad);
  838.  
  839.             inst->object_flags|=Object_Reparsing;
  840.             ReformatWindow(inst);
  841.             inst->object_flags&=~Object_Reparsing;
  842.             }
  843.         return DoSuperMethodA(cl,obj,(Msg)msg);
  844.         }
  845.     else
  846.         return DoSuperMethodA(cl,obj,(Msg)msg);
  847. }
  848.  
  849. /* WORKING ON THIS */
  850. /* TEMP COMMENT OUT */
  851. static ULONG HTMLGadClSetText(Class *cl, Object *obj, Msg msg)
  852. {
  853.  return 0;
  854. }
  855. #if FALSE
  856. static ULONG   HTMLGadClSetText(Class *cl, Object *obj, Msg msg)
  857. {
  858.   HTMLGadClData *inst = INST_DATA(cl, o);
  859.   struct TagItem *tstate, *ti;
  860.   /* Depends on header_text, footer_text, element_id, target_anchor
  861.      being set first
  862.      inst->widget_list = wptr; DEPEND 
  863.      if (text != NULL) {
  864.      if (*text == '\0'){
  865.      text = NULL;
  866.      }
  867.      inst->raw_text = text;
  868.      }
  869.      
  870.      if (header_text != NULL)    {
  871.      if (*header_text == '\0')
  872.      {
  873.      header_text = NULL;
  874.      }
  875.      inst->header_text = header_text;
  876.      }
  877.      if (footer_text != NULL) {
  878.      if (*footer_text == '\0')
  879.      {
  880.      footer_text = NULL;
  881.      }
  882.      inst->footer_text = footer_text;
  883.      }
  884.      */
  885.   DoSuperMethodA(cl, o, msg);  /* probably not needed */
  886.   /* Free up the old visited href list.  */
  887.   FreeHRefs(inst->my_visited_hrefs);
  888.   inst->my_visited_hrefs = NULL;
  889.   
  890.       
  891.   /* Free up the old visited delayed images list.  */
  892.     FreeDelayedImages(inst->my_delayed_images);
  893.   inst->my_delayed_images = NULL;
  894.   
  895.   /*   * Hide any old widgets */
  896.   //    HideWidgets(inst);
  897.   /*   inst->widget_list = wptr; DEPEND */
  898.   inst->form_list = NULL;
  899.   
  900.   if (inst->raw_text != NULL) {
  901.     inst->raw_text = text;
  902.     /* Free any old colors and pixmaps    */
  903.     // FreeColors(XtDisplay(inst),DefaultColormapOfScreen(XtScreen(inst)));
  904.     // FreeImages(inst);
  905.     
  906.     /* Parse the raw text with the HTML parser */
  907.     inst->html_objects = HTMLParse(inst->html_objects, inst->raw_text);
  908.     CallLinkCallbacks(inst); /* What do this do? [looks risky]*/
  909.   }
  910.   if (inst->header_text != NULL)    {
  911.     /* Parse the header text with the HTML parser */
  912.     inst->html_header_objects =
  913.       HTMLParse(inst->html_header_objects, inst->header_text);
  914.   }
  915.   if (inst->footer_text != NULL){
  916.     /** Parse the footer text with the HTML parser     */
  917.     inst->html_footer_objects =
  918.       HTMLParse(inst->html_footer_objects, inst->footer_text);
  919.   }
  920.   
  921.   /* Reformat the new text */
  922.   inst->max_pre_width = DocumentWidth(inst, inst->html_objects);
  923.   ReformatWindow(inst); /* Does this try to do a display?????*/
  924.   
  925. HERE
  926.   /*
  927.    * If a target anchor is passed, override the element id
  928.    * with the id of that anchor.
  929.    */
  930.   if (target_anchor != NULL)
  931.     {
  932.       int id;
  933.       
  934.       id = HTMLAnchorToId(w, target_anchor);
  935.       if (id != 0)
  936.     {
  937.       element_id = id;
  938.     }
  939.     }
  940.   
  941.   /*
  942.    * Position text at id specified, or at top if no position
  943.    * specified.
  944.    * Find the element corrsponding to the id passed in.
  945.    */
  946.   eptr = NULL;
  947.   if (element_id != 0)
  948.     {
  949.       start = inst->formatted_elements;
  950.       while (start != NULL)
  951.     {
  952.       if (start->ele_id == element_id)
  953.         {
  954.           eptr = start;
  955.           break;
  956.         }
  957.       start = start->next;
  958.     }
  959.     }
  960.   if (eptr == NULL)
  961.     {
  962.       newy = 0;
  963.     }
  964.   else
  965.     {
  966.       newy = eptr->y - 2;
  967.     }
  968.   if (newy < 0)
  969.     {
  970.       newy = 0;
  971.     }
  972.   if (newy > (inst->doc_height - (int)inst->view_height))
  973.     {
  974.       newy = inst->doc_height - (int)inst->view_height;
  975.     }
  976.   if (newy < 0)
  977.     {
  978.       newy = 0;
  979.     }
  980.   inst->scroll_x = 0;
  981.   inst->scroll_y = newy;
  982.   //    ConfigScrollBars(inst);
  983.   //    ScrollWidgets(inst);
  984.   
  985.   /*
  986.    * Display the new text
  987.    */
  988.   ViewClearAndRefresh(inst);
  989.   
  990.   /*
  991.    * Clear any previous selection
  992.    */
  993.   inst->select_start = NULL;
  994.   inst->select_end = NULL;
  995.   inst->sel_start_pos = 0;
  996.   inst->sel_end_pos = 0;
  997.   inst->new_start = NULL;
  998.   inst->new_end = NULL;
  999.   inst->new_start_pos = 0;
  1000.   inst->new_end_pos = 0;
  1001.   inst->active_anchor = NULL;
  1002.   
  1003.   inst->cached_tracked_ele = NULL;
  1004. }
  1005.  
  1006. #endif
  1007.  
  1008. /********************************************************
  1009.   The main gadget handler routine
  1010. ********************************************************/
  1011. __asm ULONG HTMLGadClDispatch(register __a0 Class *cl,
  1012.                   register __a2 Object *obj,
  1013.                   register __a1 Msg msg){
  1014. /*  kprintf("Method %08lx issued\n",msg->MethodID); */
  1015.  
  1016.   switch (msg->MethodID) { /* approx calling order */
  1017.   case OM_NEW          : return(HTMLGadClNew(cl,obj,(APTR)msg));
  1018.   case OM_DISPOSE      : return(HTMLGadClDispose(cl,obj,(APTR)msg));
  1019.   case MUIM_AskMinMax  : return(HTMLGadClAskMinMax(cl,obj,(APTR)msg));
  1020.   case MUIM_Setup      : return(HTMLGadClSetup(cl,obj,(APTR)msg));
  1021.   case MUIM_Show       : return(HTMLGadClShow(cl,obj,(APTR)msg));
  1022.   case MUIM_Hide       : return(HTMLGadClHide(cl,obj,(APTR)msg));
  1023. //  case MUIM_Draw       : return(HTMLGadClDraw(cl,obj,(APTR)msg));
  1024. //  case MUIM_HandleInput: return(HTMLGadClHandleInput(cl,obj,(APTR)msg));
  1025.   case OM_GET          : return(HTMLGadClGet(cl,obj,(APTR)msg));
  1026.   case OM_SET          : return(HTMLGadClSet(cl,obj,(APTR)msg));
  1027.   case MUIM_Cleanup    : return(HTMLGadClCleanup(cl,obj,(APTR)msg)); 
  1028.  
  1029.   /* What follows is a set of methods for doing things that used to
  1030.      be done illegally by messing with the HTMLGadget from outside it.
  1031.      They are called by cover functions in TO_HTML.c (and maybe 
  1032.      other places too, since this is legal). Note that we will
  1033.      usually have to use "set" immdiately before calling these
  1034.      methods, to prepare the structures they use. */ 
  1035.  
  1036.   case HTMLM_SetText   : return(HTMLGadClSetText(cl,obj,(APTR)msg));
  1037.   case HTMLM_ResetAmigaGadgets : return(HTMLGadClResetAmigaGadgets(cl,obj,(APTR)msg));
  1038.   case HTMLM_ResetAmigaGadgetsNoScroll : return(HTMLGadClResetAmigaGadgetsNoScroll(cl,obj,(APTR)msg));
  1039.   case HTMLM_ResetTopLeft : return(HTMLGadClResetTopLeft(cl,obj,(APTR)msg));
  1040.  
  1041. /* Methods to be implemented:
  1042.     HTMLM_LoadInlinedImages:
  1043.     HTMLM_LoadInlinedImage:
  1044.     HTMLM_ClearImageCache:
  1045.     HTMLM_GotoAnchor:
  1046. */
  1047.  
  1048.  
  1049.   }
  1050.  
  1051.     if(mui_version<11)
  1052.         if(msg->MethodID==MUIM_PlaceObject)
  1053.             return(HTMLGadClPlaceObject(cl,obj,(APTR)msg));
  1054.  
  1055.  
  1056.   return(DoSuperMethodA(cl,obj,msg));
  1057. }
  1058.  
  1059.  
  1060.  
  1061. void new_button_press(HTMLGadClData *HTML_Data,long x,long y)
  1062. {
  1063.     struct ele_rec *eptr;
  1064.     int epos;
  1065.  
  1066.     if (HTML_Data->active == FALSE) return;
  1067.  
  1068.     eptr = LocateElement(HTML_Data, x, y, &epos);
  1069.  
  1070.     if (eptr != NULL) {
  1071.         if (eptr->anchorHRef != NULL) {
  1072.             HTML_Data->active_anchor = eptr;
  1073.             HTML_Data->press_x = x;
  1074.             HTML_Data->press_y = y;
  1075.             SetAnchor(HTML_Data);
  1076.             }
  1077.         else {
  1078.             HTML_Data->new_start = NULL;
  1079.             HTML_Data->new_end = NULL;
  1080.             HTML_Data->new_start_pos = 0;
  1081.             HTML_Data->new_end_pos = 0;
  1082.             HTML_Data->press_x = x;
  1083.             HTML_Data->press_y = y;
  1084.             }
  1085.         }
  1086.     else {
  1087.         HTML_Data->new_start = NULL;
  1088.         HTML_Data->new_end = NULL;
  1089.         HTML_Data->new_start_pos = 0;
  1090.         HTML_Data->new_end_pos = 0;
  1091.         HTML_Data->press_x = x;
  1092.         HTML_Data->press_y = y;
  1093.         }
  1094. }   
  1095.  
  1096. /*
  1097.  * If we just released button one or two, and we are on an object,
  1098.  * and we have an active anchor, and we are on the active anchor,
  1099.  * and if we havn't waited too long.  Activate that anchor.
  1100.  */
  1101. void new_button_release(HTMLGadClData *HTML_Data,Object *obj,long x,long y)
  1102. {
  1103.     struct ele_rec *eptr;
  1104.     int epos;
  1105.  
  1106.     eptr = LocateElement(HTML_Data, x, y, &epos);
  1107.  
  1108.     if ((eptr != NULL)&&(eptr == HTML_Data->active_anchor)){
  1109.         if (eptr->anchorHRef != NULL){
  1110.             if ((IsDelayedHRef(HTML_Data, eptr->anchorHRef))&&
  1111.                 (HTML_Data->resolveImage != NULL)){    /* Resolve pic */
  1112.                 eptr->pic_data = (*(resolveImageProc)
  1113.                     (HTML_Data->resolveImage))(HTML_Data, eptr->edata,0);
  1114.                     /* MDF KLUDGE: If the image isn't in the cache (i.e. if the
  1115.                        resolve proc returns null) we CANNOT load it over the net.
  1116.                        We must tell the GUI that we need it to load the image, and
  1117.                        then refresh us.  What a hassle. */
  1118.  
  1119.                 if (eptr->pic_data == NULL) {
  1120.                     HTML_Data->inlined_image_to_load = eptr->edata;
  1121.                     set(obj,HTMLA_image_load,(ULONG)(eptr->edata));
  1122.                     set(G_Norm,HTMLA_image_load,(ULONG)(eptr->edata));
  1123. /*                    if(eptr->pic_data)
  1124.                         eptr->pic_data->delayed = 0;
  1125.                     else
  1126.                         kprintf("Image Not loaded\n"); */
  1127.                     }
  1128.                 }
  1129.             else if ((eptr->pic_data != NULL)&&
  1130.                 (eptr->pic_data->delayed)&&
  1131.                 (eptr->anchorHRef != NULL)&&
  1132.                 (!IsDelayedHRef(HTML_Data, eptr->anchorHRef))&&
  1133.                 ((y + HTML_Data->scroll_y - eptr->y) > AnchoredHeight(HTML_Data))) {
  1134.                     eptr->pic_data = (*(resolveImageProc)
  1135.                         (HTML_Data->resolveImage))(HTML_Data, eptr->edata,0);
  1136.                         /* MDF KLUDGE: If the image isn't in the cache (i.e. if the
  1137.                            resolve proc returns null) we CANNOT load it over the net.
  1138.                            We must tell the GUI that we need it to load the image, and
  1139.                            then refresh us.  What a hassle. */
  1140.  
  1141.                     if (eptr->pic_data == NULL) {
  1142.                         HTML_Data->inlined_image_to_load = eptr->edata;
  1143.                         set(obj,HTMLA_image_load,(ULONG)(eptr->edata));
  1144.                         set(G_Norm,HTMLA_image_load,(ULONG)(eptr->edata));
  1145. /*                        if(eptr->pic_data)
  1146.                             eptr->pic_data->delayed = 0;
  1147.                         else
  1148.                             kprintf("Image Not loaded\n"); */
  1149.                         }
  1150.                 }
  1151.                 else if ((eptr->pic_data != NULL)&&
  1152.                     (eptr->pic_data->ismap)&&
  1153.                     (eptr->anchorHRef != NULL)&&
  1154.                     (IsIsMapForm(HTML_Data, eptr->anchorHRef))) {
  1155.                         ImageSubmitForm(eptr->pic_data->fptr,
  1156.                         eptr->pic_data->text, x + HTML_Data->scroll_x - eptr->x,
  1157.                             y + HTML_Data->scroll_y -    eptr->y);
  1158.                     }
  1159.  
  1160.             else {
  1161.           /* The following is a hack to send the
  1162.            * selection location along with the HRef
  1163.            * for images.  This allows you to
  1164.            * point at a location on a map and have
  1165.            * the server send you the related document.
  1166.            * Tony Sanders, April 1993 <sanders@bsdi.com>
  1167.            */
  1168.                 char *buf = eptr->anchorHRef;
  1169.                 if (eptr->type == E_IMAGE && eptr->pic_data
  1170.                     && eptr->pic_data->ismap) {
  1171.                     buf = (char *)
  1172.                     malloc(strlen(eptr->anchorHRef) + 256);
  1173.                     sprintf(buf, "%s?%d,%d",
  1174.                     eptr->anchorHRef,
  1175.                     x + HTML_Data->scroll_x - eptr->x,
  1176.                     y + HTML_Data->scroll_y - eptr->y);
  1177.                     }
  1178.                 HTML_Data->chosen_anchor = buf;
  1179.                 set(obj,HTMLA_new_href,(ULONG)(buf));
  1180.                 set(G_Norm,HTMLA_new_href,(ULONG)(buf));
  1181.                 }
  1182.             }
  1183.         }
  1184.     UnsetAnchor(HTML_Data);
  1185. }
  1186.  
  1187.  
  1188. struct Region *installClipRegion (struct Window *w, struct Layer *l, struct Region *r)
  1189. {
  1190.     BOOL refresh = FALSE;
  1191.     struct Region *or;
  1192.  
  1193.     if (w->Flags & WINDOWREFRESH)
  1194.     {
  1195.         EndRefresh (w, FALSE);
  1196.         refresh = TRUE;
  1197.     }
  1198.     or = InstallClipRegion (l, r);
  1199.     if (refresh)
  1200.         BeginRefresh (w);
  1201.     return (or);
  1202. }
  1203.  
  1204.  
  1205. /*********************************************************************
  1206.   NAME: LoadInlinedImage(char *);
  1207.  
  1208.   DESC: Load a single inlined image over the network into the image
  1209.         cache, and refresh the HTML gadget to display the image.
  1210.  
  1211.   INPUTS: char *img -- the URL of the image to load.
  1212.  
  1213.   RETURNS: 1 if all went well, 0 if there was a problem.
  1214.  
  1215.   CALLS: ImageLoadAndCache() in img.c, to do the main work.
  1216. **********************************************************************/  
  1217. static long HTMLid=-1;
  1218. static long HTMLidscroll=-1;
  1219. long HTMLFormImages=0;
  1220.  
  1221. int LoadInlinedImage(char *img)
  1222. {
  1223.   struct Gadget *g;
  1224.   struct Window *w;
  1225.   HTMLGadClData *inst;
  1226.   void *ptr;
  1227.   char *url = mo_url_canonicalize(img, cached_url);
  1228.   int ret=0;
  1229.   long id;
  1230.  
  1231.   if (strncmp(img, "internal-", 9) == 0) return 1;
  1232.  
  1233.   if (lib_version < 39) {    /* WB 3.x needed! */
  1234.     return 0;
  1235.   }
  1236.  
  1237.     inst=INST_DATA(HTMLGadClass,HTML_Gad);
  1238.  
  1239.   ptr = mo_fetch_cached_image_data(url);
  1240.   if (!ptr) {        /* we don't have it in cache */
  1241.     inst->active = FALSE;
  1242.     Rdata.track_pointer_motion=FALSE;
  1243.     ret = ImageLoadAndCache(inst, url);
  1244.     Rdata.track_pointer_motion=TRUE;
  1245.  
  1246.     if(!inst->have_forms){
  1247.         DoMethod(App,MUIM_Application_InputBuffered);
  1248.  
  1249.         if((HTMLid==-1) || (inst->scroll_y!=HTMLidscroll)){
  1250.             HTMLid=id=HTMLPositionToId(inst,inst->scroll_y+2,0);
  1251.             }
  1252.         else
  1253.             id=HTMLid;
  1254.  
  1255.         ReformatWindow(inst);
  1256.         DoMethod(HTML_Gad,HTMLM_ResetAmigaGadgetsNoScroll);
  1257.         MUI_Redraw(HTML_Gad,MADF_DRAWOBJECT);
  1258.         HTMLGotoId(inst,id);
  1259.         HTMLidscroll=inst->scroll_y;
  1260.         }
  1261.     else
  1262.         if(ret)
  1263.             HTMLFormImages++;
  1264.  
  1265.            inst->active = TRUE;
  1266.     }
  1267.  
  1268.     return ret;
  1269. }
  1270.  
  1271.  
  1272.  
  1273. /* These have still to be looked at  (were in main.c)*/
  1274.  
  1275. /*********************************************************************
  1276.   NAME: LoadInlinedImages();
  1277.  
  1278.   DESC: Load from the network all the inlined images needed by the
  1279.         current HTML document into the image cache.
  1280.  
  1281.   INPUTS: none.
  1282.  
  1283.   CALLS: LoadInlinedImage() for each needed image.
  1284. **********************************************************************/  
  1285. extern long image_interrupt;
  1286. int LoadInlinedImages()
  1287. {
  1288.     HTMLGadClData *inst=INST_DATA(HTMLGadClass,HTML_Gad);
  1289.     char **hrefs;
  1290.     int num, i;
  1291.   
  1292.     if (lib_version < 39) {    /* WB 3.x needed! */
  1293.         return 0;
  1294.         }
  1295.  
  1296.     HTMLFormImages=0;
  1297.  
  1298.     if(!inst->have_forms){
  1299.         HTMLid=HTMLPositionToId(inst,inst->scroll_y+2,0);
  1300.         HTMLidscroll=inst->scroll_y;
  1301.         }
  1302.  
  1303.     hrefs = HTMLGetImageSrcs (inst, &(num));
  1304.     image_interrupt=0;
  1305.  
  1306.     if (num) {
  1307.         for (i=0; i<num; i++) {
  1308.             if(!image_interrupt)
  1309.                 LoadInlinedImage(hrefs[i]);
  1310.             free (hrefs[i]);
  1311.             }
  1312.         free (hrefs);
  1313.         }
  1314.  
  1315.     if(inst->have_forms && HTMLFormImages)
  1316.         set(WI_ImagesReady,MUIA_Window_Open,TRUE);
  1317.  
  1318.     HTMLid=-1;
  1319.     return 0;
  1320. }
  1321.  
  1322. /*********************************************************************
  1323.   NAME: NotifyChange()
  1324.  
  1325.   PURPOSE: Send notification event to Intuition that an attribute of
  1326.            the Boopsi gadget has changed.
  1327. *********************************************************************/
  1328. void NotifyChange(Class *cl, Object *o, struct gpInput *gpi, Tag tag,
  1329.           ULONG data){
  1330.   struct TagItem tt[3];
  1331.  
  1332.   tt[0].ti_Tag = tag;
  1333.   tt[0].ti_Data = data;
  1334.  
  1335.   tt[1].ti_Tag = GA_ID;
  1336.   tt[1].ti_Data = ((struct Gadget *)o)->GadgetID;
  1337.  
  1338.   tt[2].ti_Tag = TAG_DONE;
  1339.  
  1340.   DoSuperMethod(cl, o, OM_NOTIFY, tt, gpi->gpi_GInfo, 0);
  1341. }
  1342.  
  1343. /*********************************************************************
  1344.   NAME: ResetAmigaGadgets();
  1345.  
  1346.   DESC: After any window document is changed, this should be called to
  1347.         update the scrollbar thumb sizes and locations, and to enable
  1348.     or disable the ISINDEX search gadgets.        
  1349.  
  1350.   INPUTS: none.
  1351. **********************************************************************/  
  1352. void ResetAmigaGadgets(void)
  1353. {
  1354.     DoMethod(HTML_Gad,HTMLM_ResetAmigaGadgets);
  1355. }
  1356.  
  1357. /**********OLD JUNK **********/
  1358. /***********************************
  1359.   Memory to store information about Boopsi HTML Gadget Objects
  1360.  ***********************************/
  1361. #if FALSE
  1362. typedef struct plitem {
  1363.   struct plitem *prev;
  1364.   struct plitem *next;
  1365.   HTMLPart *part;
  1366. } HTMLPartItem;
  1367. typedef HTMLPartItem  *HTMLPartList;
  1368. static HTMLPartList globallist = (HTMLPartList)NULL;
  1369.  
  1370. HTMLPart ThePart;
  1371.  
  1372. static HTMLPart *RememberNEWHTMLAmigaData(void){
  1373.   HTMLPartItem *NewItem;
  1374.   HTMLPart     *NewPart;
  1375.   
  1376.   if (NULL == (NewPart = (HTMLPart *)malloc(sizeof(HTMLPart)))) return NULL;
  1377.   if (NULL == (NewItem = (HTMLPartItem *)malloc(sizeof(HTMLPartItem)))) {
  1378.     free(NewPart); return NULL;
  1379.   }
  1380.   NewItem->prev = (HTMLPartItem *)NULL;
  1381.   NewItem->next = (HTMLPartItem *)NULL;
  1382.   NewItem->part = NewPart;
  1383.  
  1384.   if ((HTMLPartList)NULL != globallist){
  1385.     NewItem->next = globallist;
  1386.     globallist->prev = NewItem;
  1387.   }
  1388.   globallist = NewItem;
  1389.   return NewPart;
  1390. }
  1391.  
  1392. /* public */
  1393. void ForgetHTMLAmigaData(HTMLPart * item){
  1394.   HTMLPartItem *ItemPtr;
  1395.   for (ItemPtr = globallist; (ItemPtr != NULL); ItemPtr= ItemPtr->next ) {
  1396.     if (ItemPtr->part == item){
  1397.       /* Remove if from the list */
  1398.       if (ItemPtr->prev == NULL){
  1399.     globallist = ItemPtr->next;
  1400.     if (globallist != NULL){
  1401.       globallist->prev = NULL;
  1402.     }
  1403.       } else {
  1404.     ItemPtr->prev->next = ItemPtr->next;
  1405.     if (ItemPtr->next != NULL){
  1406.       ItemPtr->next->prev = ItemPtr->prev;
  1407.     }
  1408.       }
  1409.       /* It's out of the globallist. Destroy it */
  1410.       if (ItemPtr->part != NULL) free(ItemPtr->part);
  1411.       free(ItemPtr);
  1412.       break;
  1413.     }
  1414.   }
  1415. }
  1416. /* public */
  1417. void ForgetALLHTMLAmigaData  (void){
  1418. /* Call before final exit */
  1419.   while (globallist != NULL){
  1420.     ForgetHTMLAmigaData(globallist->part);
  1421.   }
  1422. }
  1423.  
  1424. static void CheckShadowing (HTMLGadClData *inst){
  1425. /*  the htmlshadow is there so that we can detect when MUI has
  1426.     remade the widget, using remember to copy over html
  1427.     then we can delete the memory that was allocated when
  1428.     the replacement gadget was created (i.e. that pointed to
  1429.     by the shadow, and make the shadow == the original again */
  1430. /*  if (inst == NULL) return;
  1431.   if (inst == NULL) return;
  1432.   if (instshadow != NULL) {
  1433.     ForgetHTMLAmigaData(instshadow);
  1434.   }
  1435.   instshadow = inst;*/
  1436.   return;  
  1437. }
  1438. #endif
  1439.  
  1440. /* This was in HTML_img.c */
  1441.  
  1442. /*********************************************************************
  1443.   NAME: ImageLoadAndCache(HTMLPart *hw, char *src)
  1444.  
  1445.   DESC: Load a single inlined image over the network.  Use DataTypes
  1446.         to convert it to an Amiga BitMap.  Save the image in the
  1447.     cache.
  1448.  
  1449.   INPUTS: HTMLPart *hw -- pointer to the HTML gadget.
  1450.           char *img -- the _canonicalized_ URL of the image to load.
  1451.  
  1452.   RETURNS: 1 if all went well, 0 if there was a problem.
  1453.  
  1454.   CALLS: mo_cache_data()
  1455.  
  1456.   COMMENTS: We need to make our own copy of the returned BitMap so
  1457.             that we can dispose of the DataTypes object and remove
  1458.             the temporary file in T:
  1459. **********************************************************************/  
  1460.  
  1461. /* The URL should already be canonicalized.  We should know that the image
  1462.    isn't already in the cache.  */
  1463.  
  1464. extern int lib_version;
  1465.  
  1466. /*
  1467. /* This routine doesn't use transparent gifs */
  1468. int ImageLoadAndCache(HTMLGadClData *HTML_Data, char *src)
  1469. {
  1470.   APTR dtobject;
  1471.   struct BitMap *bm1 = NULL, *bm2;
  1472.   struct BitMapHeader *bmh = NULL;
  1473.   struct gpLayout mygpLayout;
  1474.   ImageInfo *img_data;
  1475.   char *fnam;
  1476.   int rc;
  1477.  
  1478.   if (!src) {
  1479.     return 0;
  1480.   }
  1481.  
  1482.   if (lib_version < 39) {    /* WB 3.x needed! */
  1483.     return 0;
  1484.   }
  1485.  
  1486.   fnam = mo_tmpnam();
  1487.   rc = mo_pull_er_over_virgin (src, fnam);
  1488.  
  1489.   if (!rc) {
  1490.     free (fnam);
  1491.     return 0;
  1492.   }
  1493.  
  1494.     img_data = malloc(sizeof(ImageInfo));
  1495.     img_data->mask_bitmap=NULL;
  1496.  
  1497.     if (dtobject = NewDTObject(fnam, DTA_GroupID,GID_PICTURE, PDTA_Remap, TRUE, TAG_DONE)){
  1498.         ULONG *pentable;
  1499.         int numpens;
  1500.         struct BitMap *OrgBitMap;
  1501.  
  1502.         GetDTAttrs(dtobject, PDTA_BitMapHeader, &bmh, TAG_DONE);
  1503.  
  1504.         SetDTAttrs(dtobject, NULL,NULL, PDTA_Screen, HTML_Data->win->WScreen,
  1505.             PDTA_FreeSourceBitMap,TRUE,TAG_DONE);
  1506.  
  1507. //        DoDTMethod(dtobject,NULL, NULL, DTM_PROCLAYOUT, NULL,1);
  1508.           DoMethod(dtobject,DTM_PROCLAYOUT,NULL,1L); /* Doesn't lock up the system while remapping */
  1509.  
  1510.         GetDTAttrs(dtobject, PDTA_BitMap, &bm1,
  1511.             PDTA_ColorTable, &pentable, PDTA_Allocated, &numpens, TAG_DONE);
  1512.  
  1513.         img_data->width = bmh->bmh_Width;
  1514.         img_data->height = bmh->bmh_Height;
  1515.         img_data->image_data = (char *)1;
  1516.         img_data->image = bm1;
  1517.         img_data->dt = dtobject;
  1518.         img_data->colors = pentable;
  1519.         img_data->fname = fnam;
  1520.  
  1521.         mo_cache_data (src, (void *)img_data, 0);
  1522.         }
  1523.  else {
  1524.       FILE *fp;
  1525.       unsigned char *data;
  1526.       int width, height, colrs, bg;
  1527.  
  1528.       fp = fopen(fnam, "r");
  1529.  
  1530.       data = ReadXbmBitmap(fp, fnam, &width, &height, &colrs);
  1531.       fclose(fp);
  1532.       if (data) {
  1533.     bm1 = CreateBitMapFromXBMData(data, width, height,
  1534.                        WIDG_DEPTH);
  1535.     img_data->width = width;
  1536.     img_data->height = height;
  1537.     img_data->image_data = (char *)1;
  1538.     img_data->image = bm1;
  1539.     img_data->dt = NULL;
  1540.     img_data->colors = NULL;
  1541.     img_data->fname = NULL;
  1542.     img_data->mask_bitmap=NULL;
  1543.       
  1544.     mo_cache_data (src, (void *)img_data, 0);
  1545.  
  1546.     unlink(fnam);
  1547.     free (fnam);
  1548.  
  1549.       } else {
  1550.  
  1551.     unlink(fnam);
  1552.     free (fnam);
  1553.     free(img_data);
  1554.     return 0;        /* datatype conversion failed! */
  1555.       }
  1556.     }      
  1557.  
  1558.   return 1;
  1559. }
  1560.  
  1561. */
  1562. /* This routine handles transparent gifs. However, it seems like it
  1563. doesn't work under cybergfx */
  1564. /*
  1565. int ImageLoadAndCache(HTMLGadClData *HTML_Data, char *src)
  1566. {
  1567.   APTR dtobject;
  1568.   struct BitMap *bm1 = NULL, *bm2;
  1569.   struct BitMapHeader *bmh = NULL;
  1570.   struct gpLayout mygpLayout;
  1571.   ImageInfo *img_data;
  1572.   char *fnam;
  1573.   int rc;
  1574.  
  1575.   if (!src) {
  1576.     return 0;
  1577.   }
  1578.  
  1579.   if (lib_version < 39) {    /* WB 3.x needed! */
  1580.     return 0;
  1581.   }
  1582.  
  1583.   fnam = mo_tmpnam();
  1584.   rc = mo_pull_er_over_virgin (src, fnam);
  1585.  
  1586.   if (!rc) {
  1587.     free (fnam);
  1588.     return 0;
  1589.   }
  1590.  
  1591.     img_data = malloc(sizeof(ImageInfo));
  1592.     img_data->mask_bitmap=NULL;
  1593.  
  1594.     if (dtobject = NewDTObject(fnam, DTA_GroupID,GID_PICTURE, PDTA_Remap, FALSE, TAG_DONE)){
  1595.         ULONG *pentable;
  1596.         int numpens;
  1597.         struct BitMap *OrgBitMap;
  1598.  
  1599.         GetDTAttrs(dtobject, PDTA_BitMapHeader, &bmh, TAG_DONE);
  1600.  
  1601.         /* Use a faked transparent color */
  1602. //        bmh->bmh_Masking=mskHasTransparentColor;
  1603. //        bmh->bmh_Transparent=0; /* Color 0 is transparent */
  1604.         if(bmh->bmh_Masking==mskHasTransparentColor){
  1605.             struct RastPort *tmpRp1,*tmpRp2;
  1606.             struct BitMap *b;
  1607.             long x,y,c=bmh->bmh_Transparent;
  1608.  
  1609. #if DEBUG1==1
  1610.             kprintf("Transparent picture\n");
  1611. #endif
  1612.  
  1613. //            DoDTMethod(dtobject,NULL, NULL, DTM_PROCLAYOUT, NULL,1);
  1614.               DoMethod(dtobject,DTM_PROCLAYOUT,NULL,1L); /* Doesn't lock up the system while remapping */
  1615.  
  1616.             GetDTAttrs(dtobject, PDTA_BitMap, &OrgBitMap, TAG_DONE);
  1617.  
  1618. //            b = AllocBitMap(bmh->bmh_Width, bmh->bmh_Height,1, BMF_CLEAR, OrgBitMap);
  1619.  
  1620.             tmpRp1=calloc(1,sizeof(struct RastPort));
  1621. //            tmpRp2=calloc(1,sizeof(struct RastPort));
  1622.  
  1623.  
  1624.             InitRastPort(tmpRp1);
  1625.             InitRastPort(tmpRp2);
  1626.  
  1627.  
  1628.             tmpRp1->BitMap=OrgBitMap;
  1629.             tmpRp2->BitMap=b;
  1630.  
  1631.             SetABPenDrMd(tmpRp2,1,1,JAM1);
  1632.  
  1633. /*            for(x=0;x<bmh->bmh_Width;x++)
  1634.                 for(y=0;y<bmh->bmh_Height;y++)
  1635.                     if(ReadPixel(tmpRp1,x,y)!=c)
  1636.                         WritePixel(tmpRp2,x,y); */
  1637.             if(tmpRp1) free(tmpRp1);
  1638.             if(tmpRp2) free(tmpRp2);
  1639.  
  1640. //            kprintf("Bmap0 %lx,",b->Planes[0]);
  1641. //            kprintf("Bmap1 %lx,",b->Planes[1]);
  1642. //            kprintf("Bmap2 %lx,",b->Planes[2]);
  1643. //            kprintf("Bmap3 %lx.\n",b->Planes[3]);
  1644.  
  1645.             img_data->mask_bitmap=b;
  1646.             }
  1647. #if DEBUG1==1
  1648.         else
  1649.         kprintf("Nontransparent picture\n");
  1650. #endif
  1651.  
  1652.         SetDTAttrs(dtobject, NULL,NULL, PDTA_Screen, HTML_Data->win->WScreen,
  1653.             PDTA_FreeSourceBitMap,TRUE,PDTA_Remap,TRUE, TAG_DONE);
  1654.  
  1655. //        DoDTMethod(dtobject,NULL, NULL, DTM_PROCLAYOUT, NULL,1);
  1656.           DoMethod(dtobject,DTM_PROCLAYOUT,NULL,1L); /* Doesn't lock up the system while remapping */
  1657.  
  1658.         GetDTAttrs(dtobject, PDTA_BitMap, &bm1,
  1659.             PDTA_ColorTable, &pentable, PDTA_Allocated, &numpens, TAG_DONE);
  1660.  
  1661.         img_data->width = bmh->bmh_Width;
  1662.         img_data->height = bmh->bmh_Height;
  1663.         img_data->image_data = (char *)1;
  1664.         img_data->image = bm1;
  1665.         img_data->dt = dtobject;
  1666.         img_data->colors = pentable;
  1667.         img_data->fname = fnam;
  1668.  
  1669.         mo_cache_data (src, (void *)img_data, 0);
  1670.         }
  1671.  else {
  1672.       FILE *fp;
  1673.       unsigned char *data;
  1674.       int width, height, colrs, bg;
  1675.  
  1676.       fp = fopen(fnam, "r");
  1677.  
  1678.       data = ReadXbmBitmap(fp, fnam, &width, &height, &colrs);
  1679.       fclose(fp);
  1680.       if (data) {
  1681.     bm1 = CreateBitMapFromXBMData(data, width, height,
  1682.                        WIDG_DEPTH);
  1683.     img_data->width = width;
  1684.     img_data->height = height;
  1685.     img_data->image_data = (char *)1;
  1686.     img_data->image = bm1;
  1687.     img_data->dt = NULL;
  1688.     img_data->colors = NULL;
  1689.     img_data->fname = NULL;
  1690.     img_data->mask_bitmap=NULL;
  1691.       
  1692.     mo_cache_data (src, (void *)img_data, 0);
  1693.  
  1694.     unlink(fnam);
  1695.     free (fnam);
  1696.  
  1697.       } else {
  1698.  
  1699.     unlink(fnam);
  1700.     free (fnam);
  1701.     free(img_data);
  1702.     return 0;        /* datatype conversion failed! */
  1703.       }
  1704.     }      
  1705.  
  1706.   return 1;
  1707. }
  1708. */
  1709.  
  1710. int ImageLoadAndCache(HTMLGadClData *HTML_Data, char *src)
  1711. {
  1712.     APTR dtobject;
  1713.     struct BitMap *bm1 = NULL, *bm2;
  1714.     struct BitMapHeader *bmh = NULL;
  1715.     struct gpLayout mygpLayout;
  1716.     ImageInfo *img_data;
  1717.     char *fnam;
  1718.     int rc;
  1719.     struct RastPort *tmpRp1,*tmpRp2;
  1720.     struct BitMap *b;
  1721.  
  1722.   if (!src) {
  1723.     return 0;
  1724.   }
  1725.  
  1726.   if (lib_version < 39) {    /* WB 3.x needed! */
  1727.     return 0;
  1728.   }
  1729.  
  1730.   fnam = mo_tmpnam();
  1731.   rc = mo_pull_er_over_virgin (src, fnam);
  1732.  
  1733.   if (!rc) {
  1734.     free (fnam);
  1735.     return 0;
  1736.   }
  1737.  
  1738.     img_data = malloc(sizeof(ImageInfo));
  1739.     img_data->mask_bitmap=NULL;
  1740.  
  1741.     if (dtobject = NewDTObject(fnam, DTA_GroupID,GID_PICTURE, PDTA_Remap, FALSE, TAG_DONE)){
  1742.         ULONG *pentable;
  1743.         int numpens;
  1744.         struct BitMap *OrgBitMap;
  1745.  
  1746.         GetDTAttrs(dtobject, PDTA_BitMapHeader, &bmh, TAG_DONE);
  1747.  
  1748.         if(bmh->bmh_Masking==mskHasTransparentColor){
  1749.             long x,y,c=bmh->bmh_Transparent;
  1750.  
  1751. #if DEBUG1==1
  1752.             kprintf("Transparent picture\n");
  1753. #endif
  1754.  
  1755.               DoMethod(dtobject,DTM_PROCLAYOUT,NULL,1L); /* Doesn't lock up the system while remapping */
  1756.             GetDTAttrs(dtobject, PDTA_BitMap, &OrgBitMap, TAG_DONE);
  1757.  
  1758.             b = AllocBitMap(bmh->bmh_Width, bmh->bmh_Height,1, BMF_CLEAR, OrgBitMap);
  1759.  
  1760.             tmpRp1=calloc(1,sizeof(struct RastPort));
  1761.             tmpRp2=calloc(1,sizeof(struct RastPort));
  1762.  
  1763.             InitRastPort(tmpRp1);
  1764.             InitRastPort(tmpRp2);
  1765.  
  1766.             tmpRp1->BitMap=OrgBitMap;
  1767.             tmpRp2->BitMap=b;
  1768.  
  1769.             SetABPenDrMd(tmpRp2,1,1,JAM1);
  1770.  
  1771.             for(x=0;x<bmh->bmh_Width;x++)
  1772.                 for(y=0;y<bmh->bmh_Height;y++)
  1773.                     if(ReadPixel(tmpRp1,x,y)!=c)
  1774.                         WritePixel(tmpRp2,x,y);
  1775.  
  1776.             }
  1777.  
  1778.         SetDTAttrs(dtobject, NULL,NULL, PDTA_Screen, HTML_Data->win->WScreen,
  1779.             PDTA_FreeSourceBitMap,TRUE,PDTA_Remap,TRUE, TAG_DONE);
  1780.  
  1781. //        DoDTMethod(dtobject,NULL, NULL, DTM_PROCLAYOUT, NULL,1);
  1782.           DoMethod(dtobject,DTM_PROCLAYOUT,NULL,1L); /* Doesn't lock up the system while remapping */
  1783.  
  1784.         GetDTAttrs(dtobject, PDTA_BitMap, &bm1,
  1785.             PDTA_ColorTable, &pentable, PDTA_Allocated, &numpens, TAG_DONE);
  1786.  
  1787.  
  1788.         if(bmh->bmh_Masking==mskHasTransparentColor){
  1789.             long x,y,c=bmh->bmh_Transparent;
  1790.  
  1791.             tmpRp1->BitMap=bm1;
  1792.  
  1793.             SetABPenDrMd(tmpRp1,0,1,JAM1);
  1794.  
  1795.             for(x=0;x<bmh->bmh_Width;x++)
  1796.                 for(y=0;y<bmh->bmh_Height;y++)
  1797.                     if(ReadPixel(tmpRp2,x,y)!=1)
  1798.                         WritePixel(tmpRp1,x,y);
  1799.  
  1800.             if(tmpRp1) free(tmpRp1);
  1801.             if(tmpRp2) free(tmpRp2);
  1802.  
  1803.             }
  1804.  
  1805.         img_data->width = bmh->bmh_Width;
  1806.         img_data->height = bmh->bmh_Height;
  1807.         img_data->image_data = (char *)1;
  1808.         img_data->image = bm1;
  1809.         img_data->dt = dtobject;
  1810.         img_data->colors = pentable;
  1811.         img_data->fname = fnam;
  1812.  
  1813.         mo_cache_data (src, (void *)img_data, 0);
  1814.         }
  1815.  else {
  1816.       FILE *fp;
  1817.       unsigned char *data;
  1818.       int width, height, colrs, bg;
  1819.  
  1820.       fp = fopen(fnam, "r");
  1821.  
  1822.       data = ReadXbmBitmap(fp, fnam, &width, &height, &colrs);
  1823.       fclose(fp);
  1824.       if (data) {
  1825.     bm1 = CreateBitMapFromXBMData(data, width, height,
  1826.                        WIDG_DEPTH);
  1827.     img_data->width = width;
  1828.     img_data->height = height;
  1829.     img_data->image_data = (char *)1;
  1830.     img_data->image = bm1;
  1831.     img_data->dt = NULL;
  1832.     img_data->colors = NULL;
  1833.     img_data->fname = NULL;
  1834.     img_data->mask_bitmap=NULL;
  1835.       
  1836.     mo_cache_data (src, (void *)img_data, 0);
  1837.  
  1838.     unlink(fnam);
  1839.     free (fnam);
  1840.  
  1841.       } else {
  1842.  
  1843.     unlink(fnam);
  1844.     free (fnam);
  1845.     free(img_data);
  1846.     return 0;        /* datatype conversion failed! */
  1847.       }
  1848.     }      
  1849.  
  1850.   return 1;
  1851. }
  1852.  
  1853. /*************** INSTANCE HANDLING (METHODS) *************/
  1854. /*
  1855. ** AskMinMax method will be called before the window is opened
  1856. ** and before layout takes place. We need to tell MUI the
  1857. ** minimum, maximum and default size of our object.
  1858. */
  1859.  
  1860. static ULONG HTMLTextClAskMinMax(Class *cl, Object *obj, struct MUIP_AskMinMax *msg){
  1861.   /*
  1862.    ** let our superclass first fill in what it thinks about sizes.
  1863.    ** this will e.g. add the size of frame and inner spacing.
  1864.    */
  1865.   DoSuperMethodA(cl,obj,(Msg)msg);
  1866.   /*
  1867.    ** now add the values specific to our object. note that we
  1868.    ** indeed need to *add* these values, not just set them!
  1869.    */
  1870.   
  1871.   msg->MinMaxInfo->MinWidth  += 9000;
  1872.   msg->MinMaxInfo->DefWidth  += 9000;
  1873.   msg->MinMaxInfo->MaxWidth  += 9000;  /* There is an unlimited val, use it*/
  1874.  
  1875.   msg->MinMaxInfo->MinHeight += 9000;
  1876.   msg->MinMaxInfo->DefHeight += 9000;
  1877.   msg->MinMaxInfo->MaxHeight += 9000; /* same here */
  1878.  
  1879.   return(0);
  1880. }
  1881.  
  1882. static ULONG HTMLTextClSetup(Class *cl, Object *obj, Msg msg){
  1883.   if (!DoSuperMethodA(cl,obj,msg))
  1884.    return FALSE;
  1885.   MUI_RequestIDCMP(obj, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY);
  1886.   return TRUE;
  1887. }
  1888.  
  1889. static ULONG HTMLTextClCleanup( Class *cl, Object *obj, Msg msg){
  1890.     MUI_RejectIDCMP(obj,IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY);
  1891.     return (DoSuperMethodA(cl,obj,msg));
  1892. }  
  1893.  
  1894. static ULONG HTMLTextClSet(Class *cl, Object *obj, Msg msg){
  1895.     HTMLTextClData *inst = INST_DATA(cl, obj);
  1896.     struct TagItem *tstate, *ti;
  1897.     long test;
  1898.  
  1899.     ti = ((opSetP)msg)->ops_AttrList;
  1900.     tstate = ti;
  1901.   
  1902.     while (ti = NextTagItem(&tstate)) {
  1903.     switch (ti->ti_Tag) {
  1904.       
  1905. //    case HTMLA_active:        inst->active = ti->ti_Data; break;
  1906. //    case HTMLA_anchor_fg:    inst->anchor_fg = ti->ti_Data; break;
  1907. //    case HTMLA_visited_fg:    inst->visitedAnchor_fg = ti->ti_Data; break;
  1908. //    case HTMLA_active_fg:    inst->activeAnchor_fg = ti->ti_Data; break;
  1909.     case HTMLA_HTML_Data:   inst->HTML_Data = (HTMLGadClData *)ti->ti_Data; break;
  1910.       
  1911.     case HTMLA_scroll_y:
  1912. /* Take care of the virtual group here */ /* OBSOLETE? */
  1913. /*        kprintf("HTML Virt gad: Getting a new Y scroll: %ld\n",ti->ti_Data);
  1914.         inst->new_scroll_value=ti->ti_Data;
  1915.         inst->new_scroll_dir=0;
  1916.         MUI_Redraw(obj,MADF_DRAWUPDATE); */
  1917.         break;
  1918.       
  1919.     case HTMLA_scroll_x:
  1920. /* Take care of the virtual group here */ /* OBSOLETE? */
  1921. /*        kprintf("HTML Virt gad: Getting a new X scroll: %ld\n",ti->ti_Data);
  1922.         inst->new_scroll_value=ti->ti_Data;
  1923.         inst->new_scroll_dir=1;
  1924.         MUI_Redraw(obj,MADF_DRAWUPDATE); */
  1925.         break;
  1926.  
  1927.     case HTMLA_Top:
  1928. /* Take care of the virtual group here */
  1929. #if DEBUG0==1
  1930.         kprintf("HTML Virt gad: Getting a new Y position: %ld\n",ti->ti_Data);
  1931. #endif
  1932.         inst->new_scroll_value=ti->ti_Data;
  1933.         inst->new_scroll_dir=0;
  1934.         inst->Flags=1; /* 1= 'DrawUpdate' */
  1935. #if DEBUG0==1
  1936.         kprintf("Setting Virtgroup top: %ld\n",ti->ti_Data);
  1937. #endif
  1938.  
  1939.         set(G_Virt,MUIA_Virtgroup_Top,ti->ti_Data);
  1940. #if DEBUG0==1
  1941.         get(G_Virt,MUIA_Virtgroup_Top,&test);
  1942.         kprintf("The virtgroup got the top value: %ld\n",test);
  1943. #endif
  1944.         inst->Flags=0; /* Done 'DrawUpdate' */
  1945. //        MUI_Redraw(obj,MADF_DRAWUPDATE); /* Is done by VirtualGroup */
  1946.         break;
  1947.       
  1948.     case HTMLA_Left:
  1949. /* Take care of the virtual group here */
  1950. #if DEBUG0==1
  1951.         kprintf("HTML Virt gad: Getting a new X position: %ld\n",ti->ti_Data);
  1952. #endif
  1953.         inst->new_scroll_value=ti->ti_Data;
  1954.         inst->new_scroll_dir=1;
  1955.         inst->Flags=1; /* 1= 'DrawUpdate' */
  1956. #if DEBUG0==1
  1957.         kprintf("Setting Virtgroup left: %ld\n",ti->ti_Data);
  1958. #endif
  1959.         set(G_Virt,MUIA_Virtgroup_Left,ti->ti_Data);
  1960. #if DEBUG0==1
  1961.         get(G_Virt,MUIA_Virtgroup_Left,&test);
  1962.         kprintf("The virtgroup got the left value: %ld\n",test);
  1963. #endif
  1964.         inst->Flags=0; /* Done 'DrawUpdate' */
  1965. //        MUI_Redraw(obj,MADF_DRAWUPDATE); /* Is done by VirtualGroup */
  1966.         break;
  1967.  
  1968.     }
  1969.   }
  1970.   return DoSuperMethodA(cl, obj, msg);
  1971. }
  1972.  
  1973.  
  1974. /*------------------------------------------------------------------------
  1975.   Draw the HTML Gadget
  1976.   ------------------------------------------------------------------------*/
  1977. static ULONG HTMLTextClDraw(Class *cl, Object *obj, struct MUIP_Draw *msg){
  1978.     HTMLTextClData *inst = INST_DATA(cl, obj);
  1979.  
  1980.     DoSuperMethodA(cl,obj,(Msg)msg);
  1981.  
  1982. //    if(!(msg->flags & MADF_DRAWOBJECT) && !(msg->flags & MADF_DRAWUPDATE))
  1983. //        return 0L;
  1984.  
  1985.     if((msg->flags & MADF_DRAWOBJECT) && (inst->Flags & 1)){ /* Redraw exposed area */
  1986.  
  1987.         int bar=inst->new_scroll_dir,value=inst->new_scroll_value;
  1988.         HTMLGadClData *HTML_Data = inst->HTML_Data;
  1989.         /*
  1990.          * If we've moved the vertical scrollbar
  1991.          */
  1992.  
  1993.         if (bar == 0){
  1994.             /*
  1995.              * We've scrolled down. Copy up the untouched part of the
  1996.              * window.  Then Clear and redraw the new area
  1997.              * exposed.
  1998.              */
  1999.             if (value > HTML_Data->scroll_y){
  2000.                 int dy;
  2001.         
  2002.                 dy = value - HTML_Data->scroll_y;
  2003.                 if (dy > HTML_Data->view_height){
  2004.                     HTML_Data->scroll_y = value;
  2005. //                    XClearArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),0, 0,HTML_Data->view_width,HTML_Data->view_height, False);
  2006.                     ViewRedisplay(HTML_Data,0, 0,HTML_Data->view_width-1,HTML_Data->view_height);
  2007.                     }
  2008.                 else{
  2009. //                    XCopyArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),XtWindow(HTML_Data->view),HTML_Data->drawGC, 0, dy,HTML_Data->view_width,HTML_Data->view_height - dy,0, 0);
  2010.                     HTML_Data->scroll_y = value;
  2011. //                    XClearArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),0, (int)HTML_Data->view_height - dy,HTML_Data->view_width, dy, False);
  2012.                     ViewRedisplay(HTML_Data,0, (int)HTML_Data->view_height - dy,HTML_Data->view_width-1, dy);
  2013.                     }
  2014.                 }
  2015.             /*
  2016.              * We've scrolled up. Copy down the untouched part of the
  2017.              * window.  Then Clear and redraw the new area
  2018.              * exposed.
  2019.              */
  2020.             else if (value < HTML_Data->scroll_y){
  2021.                 int dy;
  2022.         
  2023.                 dy = HTML_Data->scroll_y - value;
  2024.                 if (dy > HTML_Data->view_height){
  2025.                     HTML_Data->scroll_y = value;
  2026. //                    XClearArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),0, 0,HTML_Data->view_width,HTML_Data->view_height, False);
  2027.                     ViewRedisplay(HTML_Data,0, 0,HTML_Data->view_width-1,HTML_Data->view_height);
  2028.                     }
  2029.                 else{
  2030. //                    XCopyArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),XtWindow(HTML_Data->view),HTML_Data->drawGC, 0, 0,HTML_Data->view_width,HTML_Data->view_height - dy,0, dy);
  2031.                     HTML_Data->scroll_y = value;
  2032. //                    XClearArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),0, 0,HTML_Data->view_width, dy, False);
  2033.                     ViewRedisplay(HTML_Data,0, 0,HTML_Data->view_width-1, dy);
  2034.                     }
  2035.                 }
  2036.             }
  2037.         /*
  2038.          * Else we've moved the horizontal scrollbar
  2039.          */
  2040.         else if (bar == 1){
  2041.             /*
  2042.              * We've scrolled right. Copy left the untouched part of the
  2043.              * window.  Then Clear and redraw the new area
  2044.              * exposed.
  2045.              */
  2046.             if (value > HTML_Data->scroll_x){
  2047.                 int dx;
  2048.         
  2049.                 dx = value - HTML_Data->scroll_x;
  2050.                 if (dx > HTML_Data->view_width){
  2051.                     HTML_Data->scroll_x = value;
  2052. //                    XClearArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),0, 0,HTML_Data->view_width,HTML_Data->view_height-1, False);
  2053.                     ViewRedisplay(HTML_Data,0, 0,HTML_Data->view_width,HTML_Data->view_height-1);
  2054.                 }
  2055.                 else{
  2056. //                    XCopyArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),XtWindow(HTML_Data->view),HTML_Data->drawGC, dx, 0,HTML_Data->view_width - dx,HTML_Data->view_height-1,0, 0);
  2057.                     HTML_Data->scroll_x = value;
  2058. //                    XClearArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),(int)HTML_Data->view_width - dx, 0,dx, HTML_Data->view_height-1, False);
  2059.                     ViewRedisplay(HTML_Data,(int)HTML_Data->view_width - dx, 0,dx, HTML_Data->view_height-1);
  2060.                 }
  2061.             }
  2062.             /*
  2063.              * We've scrolled left. Copy right the untouched part of the
  2064.              * window.  Then Clear and redraw the new area
  2065.              * exposed.
  2066.              */
  2067.             else if (value < HTML_Data->scroll_x){
  2068.                 int dx;
  2069.         
  2070.                 dx = HTML_Data->scroll_x - value;
  2071.                 if (dx > HTML_Data->view_width){
  2072.                     HTML_Data->scroll_x = value;
  2073. //                    XClearArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),0, 0,HTML_Data->view_width,HTML_Data->view_height-1, False);
  2074.                     ViewRedisplay(HTML_Data,0, 0,HTML_Data->view_width,HTML_Data->view_height-1);
  2075.                     }
  2076.                 else{
  2077. //                    XCopyArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),XtWindow(HTML_Data->view),HTML_Data->drawGC, 0, 0,HTML_Data->view_width - dx,HTML_Data->view_height-1,dx, 0);
  2078.                     HTML_Data->scroll_x = value;
  2079. //                    XClearArea(XtDisplay(HTML_Data->view),XtWindow(HTML_Data->view),0, 0,dx, HTML_Data->view_height-1, False);
  2080.                     ViewRedisplay(HTML_Data,0, 0,dx, HTML_Data->view_height-1);
  2081.                     }
  2082.                 }
  2083.             }
  2084.             inst->Flags=0;
  2085.         }
  2086.     else
  2087.     if((msg->flags & MADF_DRAWOBJECT) && (!inst->HTML_Data->reparsing)) /* total redraw */
  2088.         ViewClearAndRefresh(inst->HTML_Data);
  2089.  
  2090. //    DoSuperMethodA(cl,obj,(Msg)msg);
  2091.  
  2092.     return 0;
  2093. }
  2094.  
  2095. static ULONG HTMLTextClHandleInput(Class *cl, Object *obj, struct MUIP_HandleInput *msg)
  2096. {
  2097.     DoSuperMethodA(cl,obj,(Msg)msg);
  2098. //    kprintf("Getting input msg\n");
  2099.     HandleInput(msg);
  2100.     return 0;
  2101. }
  2102.  
  2103. /********************************************************
  2104.   The main HTMLText handler routine
  2105. ********************************************************/
  2106. __asm ULONG HTMLTextClDispatch(register __a0 Class *cl,
  2107.                   register __a2 Object *obj,
  2108.                   register __a1 Msg msg){
  2109.  
  2110.     switch (msg->MethodID) { /* approx calling order */
  2111.         case MUIM_AskMinMax  : return(HTMLTextClAskMinMax(cl,obj,(APTR)msg));
  2112.         case MUIM_Draw       : return(HTMLTextClDraw(cl,obj,(APTR)msg));
  2113.         case OM_SET          : return(HTMLTextClSet(cl,obj,(APTR)msg));
  2114. //        case OM_NEW          : return(HTMLTextClNew(cl,obj,(APTR)msg));
  2115. //        case OM_DISPOSE      : return(HTMLTextClDispose(cl,obj,(APTR)msg));
  2116.         case MUIM_Setup      : return(HTMLTextClSetup(cl,obj,(APTR)msg));
  2117. //        case MUIM_Show       : return(HTMLTextClShow(cl,obj,(APTR)msg));
  2118.         case MUIM_HandleInput: return(HTMLTextClHandleInput(cl,obj,(APTR)msg));
  2119. //        case OM_GET          : return(HTMLTextClGet(cl,obj,(APTR)msg));
  2120.         case MUIM_Cleanup    : return(HTMLTextClCleanup(cl,obj,(APTR)msg)); 
  2121.  
  2122.   /* What follows is a set of methods for doing things that used to
  2123.      be done illegally by messing with the HTMLGadget from outside it.
  2124.      They are called by cover functions in TO_HTML.c (and maybe 
  2125.      other places too, since this is legal). Note that we will
  2126.      usually have to use "set" immdiately before calling these
  2127.      methods, to prepare the structures they use. */ 
  2128.  
  2129. //  case HTMLM_SetText   : return(HTMLGadClSetText(cl,obj,(APTR)msg));
  2130. //  case HTMLM_ResetAmigaGadgets : return(HTMLGadClResetAmigaGadgets(cl,obj,(APTR)msg));
  2131. /* Methods to be implemented:
  2132.     HTMLM_LoadInlinedImages:
  2133.     HTMLM_LoadInlinedImage:
  2134.     HTMLM_ClearImageCache:
  2135.     HTMLM_GotoAnchor:
  2136. */
  2137.  
  2138.   }
  2139.   return(DoSuperMethodA(cl,obj,msg));
  2140. }
  2141.  
  2142. /*********************  HTMLTextN  *********************/
  2143.  
  2144.  
  2145. /*************** INSTANCE HANDLING (METHODS) *************/
  2146. /*
  2147. ** AskMinMax method will be called before the window is opened
  2148. ** and before layout takes place. We need to tell MUI the
  2149. ** minimum, maximum and default size of our object.
  2150. */
  2151.  
  2152. static ULONG HTMLTextNClAskMinMax(Class *cl, Object *obj, struct MUIP_AskMinMax *msg){
  2153.   /*
  2154.    ** let our superclass first fill in what it thinks about sizes.
  2155.    ** this will e.g. add the size of frame and inner spacing.
  2156.    */
  2157.   DoSuperMethodA(cl,obj,(Msg)msg);
  2158.   /*
  2159.    ** now add the values specific to our object. note that we
  2160.    ** indeed need to *add* these values, not just set them!
  2161.    */
  2162.   
  2163.   msg->MinMaxInfo->MinWidth  += 20;
  2164.   msg->MinMaxInfo->DefWidth  += 300;
  2165.   msg->MinMaxInfo->MaxWidth  += 9000;  /* There is an unlimited val, use it*/
  2166.  
  2167.   msg->MinMaxInfo->MinHeight += 20;
  2168.   msg->MinMaxInfo->DefHeight += 350;
  2169.   msg->MinMaxInfo->MaxHeight += 9000; /* same here */
  2170.  
  2171.   return(0);
  2172. }
  2173.  
  2174. static ULONG HTMLTextNClSetup(Class *cl, Object *obj, Msg msg){
  2175.   if (!DoSuperMethodA(cl,obj,msg))
  2176.    return FALSE;
  2177.   MUI_RequestIDCMP(obj, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY);
  2178.   return TRUE;
  2179. }
  2180.  
  2181. static ULONG HTMLTextNClCleanup( Class *cl, Object *obj, Msg msg){
  2182.     MUI_RejectIDCMP(obj,IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY);
  2183.     return (DoSuperMethodA(cl,obj,msg));
  2184. }  
  2185. static ULONG HTMLTextNClSet(Class *cl, Object *obj, Msg msg){
  2186.     HTMLTextClData *inst = INST_DATA(cl, obj);
  2187.     struct TagItem *tstate, *ti;
  2188.   
  2189.     ti = ((opSetP)msg)->ops_AttrList;
  2190.     tstate = ti;
  2191.   
  2192.     while (ti = NextTagItem(&tstate)) {
  2193.     switch (ti->ti_Tag) {
  2194.       
  2195. //    case HTMLA_active:        inst->active = ti->ti_Data; break;
  2196. //    case HTMLA_anchor_fg:    inst->anchor_fg = ti->ti_Data; break;
  2197. //    case HTMLA_visited_fg:    inst->visitedAnchor_fg = ti->ti_Data; break;
  2198. //    case HTMLA_active_fg:    inst->activeAnchor_fg = ti->ti_Data; break;
  2199.     case HTMLA_HTML_Data:   inst->HTML_Data = (HTMLGadClData *)ti->ti_Data; break;
  2200.       
  2201.     case HTMLA_Top:
  2202. #if DEBUG0==1
  2203.         kprintf("HTML Text gad: Getting a new Y position: %ld\n",ti->ti_Data);
  2204. #endif
  2205.         inst->new_scroll_value=ti->ti_Data;
  2206.         inst->new_scroll_dir=0;
  2207.         MUI_Redraw(obj,MADF_DRAWUPDATE);
  2208.         break;
  2209.       
  2210.     case HTMLA_Left:
  2211. #if DEBUG0==1
  2212.         kprintf("HTML Text gad: Getting a new X position: %ld\n",ti->ti_Data);
  2213. #endif
  2214.         inst->new_scroll_value=ti->ti_Data;
  2215.         inst->new_scroll_dir=1;
  2216.         MUI_Redraw(obj,MADF_DRAWUPDATE);
  2217.         break;
  2218.     }
  2219.   }
  2220.   return DoSuperMethodA(cl, obj, msg);
  2221. }
  2222.  
  2223. static ULONG HTMLTextNClDraw(Class *cl, Object *obj, struct MUIP_Draw *msg){
  2224.     HTMLTextClData *inst = INST_DATA(cl, obj);
  2225.  
  2226.     DoSuperMethodA(cl,obj,(Msg)msg);
  2227.  
  2228.     if(!(msg->flags & MADF_DRAWOBJECT) && !(msg->flags & MADF_DRAWUPDATE))
  2229.         return 0L;
  2230.  
  2231.     if(msg->flags & MADF_DRAWUPDATE) /* scroll to position */
  2232.         ScrollToPos(inst->HTML_Data, inst->new_scroll_dir, inst->new_scroll_value);
  2233.  
  2234.     if((msg->flags & MADF_DRAWOBJECT) && !inst->HTML_Data->reparsing) /* total redraw */
  2235.         {
  2236.         /* This is necessary in case the HTMLSetText was called before the gadget
  2237.            was ready, i.e. after a window resize.  This is MUI's fault (still!) */
  2238.   
  2239.         if (inst->HTML_Data->html_objects == NULL) {
  2240. //    NotifyChange(cl, (Object *)g, (struct gpInput *)msg, HTML_mui_resize, (ULONG)NULL);
  2241.             DoMethod(HTML_Gad,HTMLM_ResetAmigaGadgets); /* Hope this is correct */
  2242.             HTMLSetText(inst->HTML_Data, inst->HTML_Data->raw_text, NULL, NULL, 0, NULL, NULL);
  2243.              }
  2244.  
  2245. /*  ReformatWindow(HTML_Data); */ /* This is done in show */
  2246.     ViewClearAndRefresh(inst->HTML_Data);
  2247.         }
  2248.     return 0;
  2249. }
  2250.  
  2251. static ULONG HTMLTextNClHandleInput(Class *cl, Object *obj, struct MUIP_HandleInput *msg)
  2252. {
  2253.     DoSuperMethodA(cl,obj,(Msg)msg);
  2254.     HandleInput(msg);
  2255.     return 0;
  2256. }
  2257.  
  2258. /********************************************************
  2259.   The main HTMLTextN handler routine
  2260. ********************************************************/
  2261. __asm ULONG HTMLTextNClDispatch(register __a0 Class *cl,
  2262.                   register __a2 Object *obj,
  2263.                   register __a1 Msg msg){
  2264.  
  2265.     switch (msg->MethodID) {
  2266.         case MUIM_AskMinMax  : return(HTMLTextNClAskMinMax(cl,obj,(APTR)msg));
  2267.         case MUIM_Draw       : return(HTMLTextNClDraw(cl,obj,(APTR)msg));
  2268.         case OM_SET          : return(HTMLTextNClSet(cl,obj,(APTR)msg));
  2269.         case MUIM_Setup      : return(HTMLTextNClSetup(cl,obj,(APTR)msg));
  2270.         case MUIM_Cleanup    : return(HTMLTextNClCleanup(cl,obj,(APTR)msg));
  2271.         case MUIM_HandleInput: return(HTMLTextNClHandleInput(cl,obj,(APTR)msg));
  2272.  
  2273. //        case MUIM_Show       : return(HTMLTextNClShow(cl,obj,(APTR)msg));
  2274.   }
  2275.   return(DoSuperMethodA(cl,obj,msg));
  2276. }
  2277.  
  2278. /*****************************************************
  2279.  * All functions below deals with forms, gadgets etc *
  2280.  *                                                   *
  2281.  * Notes:                                            *
  2282.  *    Everything is under construction, do not asume *
  2283.  *    anything about it.                             *
  2284.  *                                                   *
  2285.  * Bugs:                                             *
  2286.  *    Cannot handle History moves                    *
  2287.  *    Doesn't free everything after itself           *
  2288.  *                                                   *
  2289.  *****************************************************/
  2290.  
  2291. WidgetInfo *
  2292. FindWidget(WidgetInfo *w,long Id)
  2293. {
  2294.     for(;w;w=w->next)
  2295.         if(w->id==Id)
  2296.             return w;
  2297.     return NULL;
  2298. }
  2299.  
  2300. char **SplitOptions(char *in_str){
  2301.     char *tptr,**out,**tout,*new;
  2302.     long opt,ns;
  2303.     new=malloc(strlen(in_str)+1);
  2304.  
  2305.     strcpy(new,in_str);
  2306.  
  2307.     opt=0;
  2308.     for(tptr=new;*tptr;tptr++)
  2309.         if(*tptr=='|')
  2310.             opt++;
  2311.     if(*in_str)
  2312.         opt++;
  2313.  
  2314.     out=malloc(sizeof(char *)*(opt+1));
  2315.     ns=1;
  2316.     for(tptr=new,tout=out;*tptr;tptr++){
  2317.         if(ns){
  2318.             *tout++=tptr;
  2319.             ns=0;
  2320.             }
  2321.         if(*tptr=='|'){
  2322.             *tptr=0x0;
  2323.             ns=1;
  2324.             }
  2325.         }
  2326.     *tout=NULL;
  2327.     return out;
  2328. }
  2329.  
  2330. #define FTYPE_NOTSET   0   /* Just to know if we have done anything or not */
  2331. #define FTYPE_TEXT     1   /* These are just preliminary types */
  2332. #define FTYPE_TEXTAREA 2
  2333. #define FTYPE_LISTV    3
  2334. #define FTYPE_ISINDEX  4
  2335. #define FTYPE_CYCLE    5
  2336. #define FTYPE_HIDDEN   6   /* Just some text to send to the cgi-bin */
  2337. #define FTYPE_BUTTON_S 7   /* Button submit */
  2338. #define FTYPE_BUTTON_R 11  /* Button reset */
  2339. #define FTYPE_BUTTON_C 13  /* Button clear */
  2340. #define FTYPE_PASSWORD 8
  2341. #define FTYPE_CHECKBOX 9
  2342. #define FTYPE_RADIO    10
  2343. #define FTYPE_SELECT   12  /* This is both a cycle and a list view */
  2344. #define FTYPE_UNKNOWN 999 /* I hope it never will be needed */
  2345.  
  2346. /*
  2347. radio     100% working
  2348. checkbox  100% working
  2349. text      100% working
  2350. password  100% working
  2351. submit    100% working
  2352. reset     100% working
  2353. hidden    100% working
  2354.  
  2355. listv     100% working
  2356. cycle     100% working
  2357.  
  2358. textarea   20% working
  2359. isindex   100%
  2360. */
  2361.  
  2362. ULONG ParseWidgetType(char *type)
  2363. {
  2364.     if(type){ /* Make sure it isn't a NULL pointer */
  2365.         if(!strnicmp(type,"hidden",7))
  2366.             return FTYPE_HIDDEN;
  2367.         if(!strnicmp(type,"text",5))
  2368.             return FTYPE_TEXT;
  2369.         if(!strnicmp(type,"password",9))
  2370.             return FTYPE_PASSWORD;
  2371.         if(!strnicmp(type,"checkbox",9))
  2372.             return FTYPE_CHECKBOX;
  2373.         if(!strnicmp(type,"radio",6))
  2374.             return FTYPE_RADIO;
  2375.         if(!strnicmp(type,"textarea",9))
  2376.             return FTYPE_TEXTAREA;
  2377.         if(!strnicmp(type,"select",7))
  2378.             return FTYPE_SELECT;
  2379.  
  2380.         if(!strnicmp(type,"submit",7))
  2381.             return FTYPE_BUTTON_S;
  2382.         if(!strnicmp(type,"reset",6))
  2383.             return FTYPE_BUTTON_R;
  2384.         if(!strnicmp(type,"clear",6))
  2385.             return FTYPE_BUTTON_C;
  2386.         }
  2387.     return FTYPE_UNKNOWN; /* The stupid author of the page has left the type out. */
  2388. }                         /* Now I have to determine it by myself. */
  2389.  
  2390. ULONG GetTextWidth(char **text)
  2391. {
  2392.     if(text){
  2393.         ULONG size=0,l;
  2394.         while(*text){
  2395.             l=strlen(*text);
  2396.             if(l>size)
  2397.                 size=l;
  2398.             text++;
  2399.             }
  2400.         return size;
  2401.         }
  2402.     return 0;
  2403. }
  2404.  
  2405. WidgetInfo *
  2406. MakeWidget(HTMLGadClData *HTML_Data, char *edata,
  2407.                 long x,long y,long WidgetId,FormInfo *Form)
  2408. {
  2409.     WidgetInfo *widget,*cw;
  2410.     char *tptr;
  2411.     char *type,*value,*name,*options;
  2412.     long size,width,height,crows,ccols,widgettype;
  2413.  
  2414. //    kprintf("Called MakeWidget\n");
  2415. //    kprintf("FormInfo : action: %s method: %s\n",Form->action,Form->method);
  2416. //    kprintf("Edata: -%s-, WidgetId: %ld\n",edata,WidgetId);
  2417. //    kprintf("Cords x: %ld y: %ld\n",x,y);
  2418.  
  2419.     if(HTML_Data->object_flags & Object_Reparsing){
  2420.         if(widget=FindWidget(HTML_Data->widget_list,WidgetId)){
  2421.             widget->flags=0;
  2422.             widget->ParentForm=Form; /* To have a link back */
  2423.             SetAttrs(widget->MUI_Object,
  2424.                 MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left-HTML_Data->scroll_x),
  2425.                 MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top-HTML_Data->scroll_y),TAG_DONE);
  2426.             GetAttr(MUIA_NewGroup_Width,widget->MUI_Object,(ULONG *)&widget->width);
  2427.             GetAttr(MUIA_NewGroup_Height,widget->MUI_Object,(ULONG *)&widget->height);
  2428.             }
  2429.         return widget;
  2430.         }
  2431.  
  2432.     if(widget=FindWidget(HTML_Data->widget_list,WidgetId)){
  2433.         /* If this is true the old widget has just got some new cordinates */
  2434.         widget->flags=0;
  2435.         widget->ParentForm=Form; /* To have a link back */
  2436.         SetAttrs(widget->MUI_Object,
  2437.             MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2438.             MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),TAG_DONE);
  2439.             return widget;
  2440.         }        
  2441.  
  2442.     widget=calloc(1,sizeof(WidgetInfo));
  2443.  
  2444.     type=ParseMarkTag(edata,MT_INPUT,"TYPE");
  2445.     value=NULL;
  2446.  
  2447.     if((widget->type=ParseWidgetType(type))==FTYPE_UNKNOWN){
  2448.         /* Try to find out what sort of input tag this is */
  2449.         widget->type=FTYPE_TEXT; /* Default is text entry */
  2450.         }
  2451.  
  2452.     name=ParseMarkTag(edata,MT_INPUT,"NAME");
  2453.     height=14;
  2454.     width=64;
  2455.  
  2456.     switch(widget->type){
  2457.         case FTYPE_BUTTON_S:
  2458.         case FTYPE_BUTTON_R:
  2459.         case FTYPE_BUTTON_C:
  2460.             value=ParseMarkTag(edata,MT_INPUT,"VALUE");
  2461.             if(!value || *value==0x0){
  2462.             
  2463.                 if(widget->type==FTYPE_BUTTON_S)
  2464.                     value=strdup("Submit");
  2465.                 else
  2466.                     if(widget->type==FTYPE_BUTTON_R)
  2467.                         value=strdup("Reset");}
  2468.             else{
  2469.                 if(!strnicmp(value,"clear",5))
  2470.                     widget->type=FTYPE_BUTTON_C;
  2471.                 }
  2472.             widget->MUI_Object=NewObject(NewGroupClass,NULL,
  2473.                                     MUIA_NewGroup_ChildWidth,TRUE,
  2474.                                     MUIA_NewGroup_ChildHeight,TRUE,
  2475.                                     MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2476.                                     MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),
  2477.                                     Child,widget->MUI_SubObject=SimpleButton(value),
  2478.                                     TAG_DONE);
  2479.             DoMethod(widget->MUI_SubObject,MUIM_Notify,MUIA_Pressed,FALSE,
  2480.                     widget->MUI_SubObject,4,MUIM_CallHook,&FormButton_hook,widget,Form);
  2481.             if(widget->type==FTYPE_BUTTON_S && name){
  2482. //                value=name;
  2483. //                name=strdup("submit");
  2484.                 free(value);
  2485.                 value=strdup("submit");
  2486.                 }
  2487.             width=strlen(value)*8+8;
  2488.             break;
  2489.         case FTYPE_TEXT:
  2490.         case FTYPE_PASSWORD:{
  2491.             LONG size,maxsize;
  2492.             tptr=ParseMarkTag(edata,MT_INPUT,"SIZE");
  2493.             if(tptr)
  2494.                 size=atoi(tptr);
  2495.             else
  2496.                 size=20;
  2497.             free(tptr);
  2498.             tptr=ParseMarkTag(edata,MT_INPUT,"MAXLENGTH");
  2499.             if(tptr)
  2500.                 maxsize=atoi(tptr)+1; /* +1 For the NULL byte */
  2501.             else
  2502.                 maxsize=256;
  2503.             free(tptr);
  2504.             value=ParseMarkTag(edata,MT_INPUT,"VALUE");
  2505.  
  2506.             if(widget->type==FTYPE_TEXT)
  2507.                 widget->MUI_Object=NewObject(NewGroupClass,NULL,
  2508.                                 MUIA_NewGroup_Width,size*8+4,
  2509.                                 MUIA_NewGroup_ChildHeight,TRUE,
  2510.                                 MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2511.                                 MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),
  2512.                                 Child,widget->MUI_SubObject=StringObject,StringFrame,
  2513.                                                 MUIA_String_MaxLen,maxsize,
  2514.                                 End,
  2515.                             TAG_DONE);
  2516.             else
  2517.                 widget->MUI_Object=NewObject(NewGroupClass,NULL,
  2518.                                 MUIA_NewGroup_Width,size*8+4,
  2519.                                 MUIA_NewGroup_ChildHeight,TRUE,
  2520.                                 MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2521.                                 MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),
  2522.                                 Child,widget->MUI_SubObject=StringObject,StringFrame,
  2523.                                                 MUIA_String_MaxLen,maxsize,
  2524.                                                 MUIA_String_Secret,TRUE,End,
  2525.                             TAG_DONE);
  2526.             if(value)
  2527.                 set(widget->MUI_SubObject,MUIA_String_Contents,value);
  2528.             height=11;
  2529.             width=size*8+4;
  2530.  
  2531.             break;}
  2532.         case FTYPE_HIDDEN:{
  2533.             value=ParseMarkTag(edata,MT_INPUT,"VALUE");
  2534.             width=0;
  2535.             height=0;
  2536.             break;}
  2537.         case FTYPE_TEXTAREA:{
  2538.             LONG ccols,crows;
  2539.             tptr=ParseMarkTag(edata,MT_INPUT,"COLS");
  2540.             if(tptr) ccols=atoi(tptr);
  2541.             else ccols=10; /* This should never happen */
  2542.             free(tptr);
  2543.             tptr=ParseMarkTag(edata,MT_INPUT,"ROWS");
  2544.             if(tptr) crows=atoi(tptr);
  2545.             else crows=10; /* This should never happen */
  2546.             free(tptr);
  2547.  
  2548.             tptr=ParseMarkTag(edata,MT_INPUT,"value");
  2549.             widget->MUI_Object=NewObject(NewGroupClass,NULL,
  2550.                         MUIA_NewGroup_ChildWidth,TRUE,
  2551.                         MUIA_NewGroup_ChildHeight,TRUE,
  2552.                         MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2553.                         MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),
  2554.                         Child,widget->MUI_SubObject=NewObject(TextEditFieldClass,NULL,
  2555.                             MUIA_TEF_Width,ccols,MUIA_TEF_Height,crows,
  2556.                             MUIA_TEF_Text,tptr,
  2557.                             MUIA_TEF_Active,FALSE,
  2558.                             TAG_DONE),
  2559.                         TAG_DONE);
  2560.             DoMethod(widget->MUI_SubObject,MUIM_Notify,MUIA_TEF_Active,MUIV_EveryTime,
  2561.                     widget->MUI_SubObject,2,MUIM_CallHook,&TextEdit_hook);
  2562.             width=ccols*8+24;
  2563.             height=crows*8+16;
  2564.             break;}
  2565.         case FTYPE_CHECKBOX:{
  2566.             value=ParseMarkTag(edata,MT_INPUT,"VALUE");
  2567.             if(!value)
  2568.                 value=strdup("on");
  2569.             widget->MUI_Object=NewObject(NewGroupClass,NULL,
  2570.                         MUIA_NewGroup_ChildWidth,TRUE,
  2571.                         MUIA_NewGroup_ChildHeight,TRUE,
  2572.                         MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2573.                         MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),
  2574.                         Child,widget->MUI_SubObject=ImageObject,ButtonFrame,MUIA_InputMode,MUIV_InputMode_Toggle,
  2575.                             MUIA_Image_FreeHoriz,TRUE,MUIA_Image_FreeVert,TRUE,
  2576.                             MUIA_Image_Spec,MUII_CheckMark,
  2577.                             MUIA_Background,MUII_BACKGROUND,
  2578.                             End,
  2579.                         TAG_DONE);
  2580.             if(tptr=ParseMarkTag(edata,MT_INPUT,"CHECKED")){
  2581.                 set(widget->MUI_SubObject,MUIA_Selected,TRUE);
  2582.                 widget->checked=TRUE;
  2583.                 free(tptr);
  2584.                 }
  2585.             width=24;
  2586.             height=16;
  2587.             break;}
  2588.         case FTYPE_RADIO:{
  2589.             value=ParseMarkTag(edata,MT_INPUT,"VALUE");
  2590.             if(!value)
  2591.                 value=strdup("on");
  2592.             widget->MUI_Object=NewObject(NewGroupClass,NULL,
  2593.                         MUIA_NewGroup_ChildWidth,TRUE,
  2594.                         MUIA_NewGroup_ChildHeight,TRUE,
  2595.                         MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2596.                         MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),
  2597.                         Child,widget->MUI_SubObject=ImageObject,MUIA_InputMode,MUIV_InputMode_Immediate,
  2598.                             MUIA_Image_FreeHoriz,TRUE,MUIA_Image_FreeVert,TRUE,
  2599.                             MUIA_Image_Spec,MUII_RadioButton,
  2600.                             MUIA_Background,MUII_BACKGROUND,
  2601.                             End,
  2602.                         TAG_DONE);
  2603.             if(tptr=ParseMarkTag(edata,MT_INPUT,"CHECKED")){
  2604.                 set(widget->MUI_SubObject,MUIA_Selected,TRUE);
  2605.                 free(tptr);
  2606.                 widget->checked=TRUE;
  2607.                 }
  2608.             DoMethod(widget->MUI_SubObject,MUIM_Notify,MUIA_Selected,TRUE,
  2609.                     widget->MUI_SubObject,3,MUIM_CallHook,&FormRadio_hook,widget);
  2610.  
  2611.             width=16;
  2612.             height=10;
  2613.             break;}
  2614.         case FTYPE_SELECT:{
  2615.             char **cyclelist,**selectedlist,**valuelist,**returnlist, *returns,*selected;
  2616.             long i,n;
  2617.             tptr=ParseMarkTag(edata,MT_INPUT,"MULTIPLE");
  2618.             if(tptr){
  2619.             widget->type=FTYPE_LISTV; /* Somewhat dirty to change the type on the fly, but quite handy. */
  2620.             selected=ParseMarkTag(edata,MT_INPUT,"VALUE");
  2621.             selectedlist=SplitOptions(selected);
  2622.  
  2623. //            kprintf("Selected %s\n",selected);
  2624.  
  2625.             options=ParseMarkTag(edata,MT_INPUT,"OPTIONS");
  2626.             cyclelist=SplitOptions(options);
  2627.  
  2628.             returns=ParseMarkTag(edata,MT_INPUT,"RETURNS");
  2629.             returnlist=SplitOptions(returns);
  2630.  
  2631. /*            selectedlist=SplitOpions(selected); */
  2632.  
  2633.             widget->option=(char *)cyclelist;
  2634.             widget->returnv=(char *)returnlist;
  2635.             value=(char *)selectedlist;            
  2636.  
  2637.             widget->MUI_Object=NewObject(NewGroupClass,NULL,
  2638.                         MUIA_NewGroup_Width,128,
  2639.                         MUIA_NewGroup_Height,48,
  2640.                         MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2641.                         MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),
  2642.                         Child,ListviewObject,
  2643.                             MUIA_Listview_MultiSelect,MUIV_Listview_MultiSelect_Def,
  2644.                             MUIA_Listview_List,widget->MUI_SubObject=ListObject,
  2645.                                 InputListFrame,
  2646.                                 MUIA_List_SourceArray, cyclelist,
  2647.                                 End,
  2648.                             End,
  2649.                         TAG_DONE);
  2650.             for(i=0;cyclelist[i];i++)
  2651.                 for(n=0;selectedlist[n];n++)
  2652.                     if(!stricmp(cyclelist[i],selectedlist[n]))
  2653.                         DoMethod(widget->MUI_SubObject,MUIM_List_Select,i,MUIV_List_Select_On,NULL);
  2654.  
  2655.             width=128;
  2656.             height=64;
  2657.             }
  2658.             else
  2659.             {
  2660.             widget->type=FTYPE_CYCLE; /* Somewhat dirty to change the type on the fly, but quite handy. */
  2661.             value=ParseMarkTag(edata,MT_INPUT,"VALUE");
  2662.             options=ParseMarkTag(edata,MT_INPUT,"OPTIONS");
  2663.             cyclelist=SplitOptions(options);
  2664.  
  2665.             returns=ParseMarkTag(edata,MT_INPUT,"RETURNS");
  2666.             returnlist=SplitOptions(returns);
  2667.  
  2668.             for(n=0;cyclelist[n];n++)
  2669.                 if(!stricmp(cyclelist[n],value))
  2670.                     break;
  2671.  
  2672.             widget->option=(char *)cyclelist;
  2673.             widget->returnv=(char *)returnlist;
  2674.             widget->MUI_Object=NewObject(NewGroupClass,NULL,
  2675.                         MUIA_NewGroup_ChildWidth,TRUE,
  2676.                         MUIA_NewGroup_ChildHeight,TRUE,
  2677.                         MUIA_NewGroup_Left,x+mui_add(HTML_Data->view_left),
  2678.                         MUIA_NewGroup_Top,y+mui_add(HTML_Data->view_top),
  2679.                         Child,widget->MUI_SubObject=CycleObject,MUIA_Cycle_Entries,cyclelist,End,
  2680.                         TAG_DONE);
  2681.             if(cyclelist[n])
  2682.                 set(widget->MUI_Object,MUIA_Cycle_Active,n);
  2683.  
  2684.  
  2685.             width=GetTextWidth(cyclelist)*8+24;
  2686.             height=16;
  2687.             }
  2688.             break;}
  2689.         }
  2690.  
  2691.     widget->height=height;
  2692.     widget->width=width;
  2693.     widget->x=x;
  2694.     widget->y=y;
  2695.     widget->id=WidgetId;
  2696.     widget->name=name;
  2697.     widget->value=value;
  2698.     widget->flags=0;
  2699.  
  2700.     widget->ParentForm=Form; /* To have a link back */
  2701.  
  2702.     cw=HTML_Data->widget_list;
  2703.     if(cw){
  2704.         for(;cw->next;cw=cw->next);
  2705.         cw->next=widget;
  2706.         }
  2707.     else
  2708.         HTML_Data->widget_list=widget;    
  2709.     widget->next=NULL;
  2710.  
  2711.     return widget;
  2712. }
  2713.  
  2714. void AddNewForm(HTMLGadClData *HTML_Data,FormInfo *Form){
  2715. /* This should probably set up all fields that should be
  2716.    returned by the form etc */
  2717.     WidgetInfo *cw;
  2718.     FormPartInfo *fp,*lfp=NULL;
  2719.  
  2720.     Object *stringgadget=NULL;
  2721.  
  2722. //    kprintf("Called Add new form: %08lx\n",Form);
  2723.  
  2724.     Form->href=Form->action;
  2725.  
  2726.     for(cw=HTML_Data->widget_list;cw;cw=cw->next){
  2727.     if((cw->flags == 0) && (cw->ParentForm==Form)){
  2728.         fp=calloc(1,sizeof(FormPartInfo));
  2729.         cw->flags=1;
  2730.  
  2731.         fp->Name=cw->name;
  2732.         fp->Type=cw->type;
  2733.         fp->Widget=cw;
  2734.         if(lfp)
  2735.             lfp->Next=fp;
  2736.         else
  2737.             Form->FirstFormPart=fp;
  2738.         lfp=fp;
  2739.         
  2740.         switch(cw->type){
  2741.             case FTYPE_TEXT:
  2742.                 fp->UserData=cw->MUI_SubObject;
  2743.                 if(stringgadget==0)
  2744.                     stringgadget=cw->MUI_SubObject;
  2745.                 else
  2746.                     stringgadget=(Object *)-1;
  2747.                 break;
  2748.             case FTYPE_PASSWORD:
  2749.             case FTYPE_TEXTAREA:
  2750.             case FTYPE_CYCLE:
  2751.             case FTYPE_LISTV:
  2752.                 fp->UserData=cw->MUI_SubObject;
  2753.                 stringgadget=(Object *)-1;
  2754.             break;
  2755.             case FTYPE_HIDDEN:
  2756.                 fp->UserData=cw;
  2757.                 stringgadget=(Object *)-1;
  2758.             break;
  2759.         case FTYPE_CHECKBOX:
  2760.         {
  2761.                 WidgetInfo *dw;
  2762.                 long c=0;
  2763.                 WidgetInfo **wlist;
  2764.                 if(cw->name)
  2765.                     for(dw=HTML_Data->widget_list;dw;dw=dw->next)
  2766.                         if((dw->flags == 0) && (dw->ParentForm==Form) && (dw->type==FTYPE_CHECKBOX))
  2767.                             if(dw->name)
  2768.                                 if(stricmp(dw->name,cw->name)==0)
  2769.                                     c++;
  2770.                 wlist=malloc(c*4+8);
  2771.                 fp->UserData=(APTR)wlist;
  2772.                 *wlist++=cw;
  2773.                 if(cw->name)
  2774.                     for(dw=HTML_Data->widget_list;dw;dw=dw->next)
  2775.                         if((dw->flags == 0) && (dw->ParentForm==Form) && (dw->type==FTYPE_CHECKBOX))
  2776.                             if(dw->name)
  2777.                                 if(stricmp(dw->name,cw->name)==0){
  2778.                                     *wlist++=dw;
  2779.                                     dw->flags|=1; /* Done */
  2780.                                     }
  2781.                 *wlist=NULL;}
  2782.                 stringgadget=(Object *)-1;
  2783.             break;
  2784.         case FTYPE_RADIO:{
  2785.                 WidgetInfo *dw;
  2786.                 long c=0;
  2787.                 WidgetInfo **wlist;
  2788.                 if(cw->name)
  2789.                     for(dw=HTML_Data->widget_list;dw;dw=dw->next)
  2790.                         if((dw->flags == 0) && (dw->ParentForm==Form) && (dw->type==FTYPE_RADIO))
  2791.                             if(dw->name)
  2792.                                 if(stricmp(dw->name,cw->name)==0)
  2793.                                     c++;
  2794.                 wlist=malloc(c*4+8);
  2795.                 fp->UserData=(APTR)wlist;
  2796.                 *wlist++=cw;
  2797.                 if(cw->name)
  2798.                     for(dw=HTML_Data->widget_list;dw;dw=dw->next)
  2799.                         if((dw->flags == 0) && (dw->ParentForm==Form) && (dw->type==FTYPE_RADIO))
  2800.                             if(dw->name)
  2801.                                 if(stricmp(dw->name,cw->name)==0){
  2802.                                     *wlist++=dw;
  2803.                                     dw->flags|=1; /* Done */
  2804.                                     }
  2805.                 *wlist=NULL;
  2806.                 
  2807.                 dw=NULL;
  2808.                 for(wlist=(WidgetInfo **)fp->UserData;*wlist;wlist++){
  2809.                     (*wlist)->PrevRadio=dw;
  2810.                     (*wlist)->NextRadio=wlist[1]; /* Next element */
  2811.                     dw=*wlist;
  2812.                     }
  2813.                 }
  2814.                 stringgadget=(Object *)-1;
  2815.             break;
  2816.             }
  2817.         }
  2818.     }
  2819.     if(stringgadget && (stringgadget!=(Object *)-1)){
  2820.         DoMethod(stringgadget,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
  2821.                 stringgadget,4,MUIM_CallHook,&FormString_hook,NULL,Form);
  2822.         }
  2823. }
  2824.  
  2825. void AddNewWidgets(HTMLGadClData *HTML_Data)
  2826. {
  2827.     WidgetInfo *widget,*cw,*ow;
  2828.     struct Window *win;
  2829.  
  2830.     if(HTML_Data->widget_list){
  2831.         if(!(HTML_Data->object_flags&Object_Changing)){
  2832.             HTML_Data->object_flags|=Object_Changing;
  2833.  
  2834.             if(mui_version<11){
  2835.                 set(HTML_Gad,HTMLA_Top,0);
  2836.                 set(HTML_Gad,HTMLA_Left,0);
  2837.                 set(WI_Wait,MUIA_Window_Open,TRUE); /* Before WI_Main to keep mui from closing pubscreen */
  2838.                 HTML_Data->have_formsI=1;
  2839.                 set(WI_Main, MUIA_Window_Open, FALSE); /* To be able to add the objects */
  2840.                 get(WI_Wait,MUIA_Window_Window,&win);
  2841.                 HTML_Data->rp=win->RPort; /* This is VERY ugly! */ /* But it works :) */
  2842.  
  2843. //                kprintf("Closing window...\n");
  2844.                 }
  2845.             else
  2846.                 DoMethod(HTML_Gad,MUIM_Group_InitChange); /* To be able to add the objects */
  2847.             }
  2848.         set(HTML_Gad,MUIA_Group_ActivePage,1);
  2849.         for(cw=HTML_Data->widget_list;cw;cw=cw->next){
  2850. //            kprintf("Adding object...\n");
  2851.             DoMethod(G_Virt,OM_ADDMEMBER,cw->MUI_Object);
  2852.             }
  2853.         HTML_Data->have_forms=1;
  2854. //        DoMethod(App,MUIM_Application_SetMenuState,mo_expand_images_current,FALSE);
  2855. //        DoMethod(App,MUIM_Application_SetMenuState,mo_delay_image_loads,FALSE);
  2856.         DoMethod(App,MUIM_Application_SetMenuState,mo_clear_image_cache,FALSE);
  2857.         DoMethod(App,MUIM_Application_SetMenuState,mo_isindex_to_form,FALSE);
  2858.  
  2859.         if(mui_version<11){
  2860.             DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_text,FALSE);
  2861.             DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_image,FALSE);
  2862.             DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_imagetext,FALSE);
  2863.             }
  2864.         }
  2865. }
  2866. void DisposeWidget(WidgetInfo *w)
  2867. {
  2868.     if(w->name)
  2869.         free(w->name);
  2870.     if(w->value)
  2871.         free(w->value);
  2872.     if(w->option)
  2873.         free(w->option);
  2874.  
  2875.     switch(w->type){
  2876.         case FTYPE_TEXT:
  2877.         case FTYPE_PASSWORD:
  2878.         case FTYPE_HIDDEN:
  2879.         case FTYPE_TEXTAREA:
  2880.             break;
  2881.         case FTYPE_CYCLE:
  2882.         case FTYPE_LISTV:
  2883.             if(w->returnv) free(w->returnv);
  2884.             break;
  2885.         case FTYPE_CHECKBOX:
  2886.         case FTYPE_RADIO:
  2887.         break;
  2888.         }
  2889.  
  2890.     free(w);
  2891. }
  2892.  
  2893. void DisposeForms(FormInfo *Form){
  2894. /* This should probably set up all fields that should be
  2895.    returned by the form etc */
  2896.     FormPartInfo *fp,*lfp=NULL;
  2897.     FormInfo *lfi;
  2898.  
  2899.     for(;Form;Form=lfi){
  2900.         for(fp=Form->FirstFormPart;fp;fp=lfp){
  2901.             switch(fp->Type){
  2902.                 case FTYPE_TEXT:
  2903.                 case FTYPE_PASSWORD:
  2904.                 case FTYPE_TEXTAREA:
  2905.                 case FTYPE_CYCLE:
  2906.                 case FTYPE_LISTV:
  2907.                 case FTYPE_HIDDEN:
  2908.                     break;
  2909.                 case FTYPE_CHECKBOX:
  2910.                 case FTYPE_RADIO:
  2911.                     if(fp->UserData) free(fp->UserData);
  2912.                     break;
  2913.                 }
  2914.                 lfp=fp->Next;
  2915.                 free(fp);
  2916.             }
  2917.         lfi=Form->next;
  2918.         free(Form);
  2919.         }
  2920. }
  2921.  
  2922. void HideWidgets(HTMLGadClData *HTML_Data)
  2923. {
  2924.     WidgetInfo *ow,*nw;
  2925.     struct Window *win;
  2926.  
  2927.     if(HTML_Data->widget_list){
  2928.         HTML_Data->object_flags|=Object_Changing;
  2929.  
  2930.         if(mui_version<11){
  2931.             set(HTML_Gad,HTMLA_Top,0);
  2932.             set(HTML_Gad,HTMLA_Left,0);
  2933.             set(WI_Wait,MUIA_Window_Open,TRUE); /* Before WI_Main to keep mui from closing pubscreen */
  2934.             HTML_Data->have_formsI=1;
  2935.             set(WI_Main, MUIA_Window_Open, FALSE); /* To be able to add the objects */
  2936.             get(WI_Wait,MUIA_Window_Window,&win);
  2937.             HTML_Data->rp=win->RPort; /* This is VERY ugly! */ /* But it works :) */
  2938.  
  2939. //            kprintf("Closing window...\n");
  2940.             }
  2941.         else
  2942.             DoMethod(HTML_Gad,MUIM_Group_InitChange); /* To be able to add the objects */
  2943.  
  2944.         for(ow=HTML_Data->widget_list;ow;ow=nw){
  2945. //            kprintf("Removing object...\n");
  2946.             DoMethod(G_Virt,OM_REMMEMBER,ow->MUI_Object);
  2947.             DisposeObject(ow->MUI_Object);
  2948.             nw=ow->next;
  2949.             DisposeWidget(ow);
  2950.             }
  2951.         HTML_Data->widget_list=NULL;
  2952.         }
  2953. }
  2954.  
  2955. void ShowHtml_RG(void)
  2956. {
  2957.     HTMLGadClData *HTML_Data=INST_DATA(HTMLGadClass,HTML_Gad);
  2958.  
  2959.     if(!window.binary_transfer){
  2960.  
  2961.     if(mui_version>=11){
  2962.         HTML_Data->scroll_y=HTML_Data->new_scroll_y;
  2963.         DoMethod(HTML_Gad,HTMLM_ResetAmigaGadgets);
  2964.         }
  2965.     else
  2966.         if(!HTML_Data->have_forms){
  2967.             DoMethod(HTML_Gad,HTMLM_ResetAmigaGadgets);
  2968.             }
  2969.  
  2970.     if(HTML_Data->object_flags & Object_Changing){
  2971.         if(!HTML_Data->widget_list){
  2972. //            DoMethod(App,MUIM_Application_SetMenuState,mo_expand_images_current,TRUE);
  2973. //            DoMethod(App,MUIM_Application_SetMenuState,mo_delay_image_loads,TRUE);
  2974.             DoMethod(App,MUIM_Application_SetMenuState,mo_clear_image_cache,TRUE);
  2975.             DoMethod(App,MUIM_Application_SetMenuState,mo_isindex_to_form,TRUE);
  2976.  
  2977.             if(mui_version<11){
  2978.                 DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_text,TRUE);
  2979.                 DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_image,TRUE);
  2980.                 DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_imagetext,TRUE);
  2981.                 }
  2982.             HTML_Data->have_forms=0;
  2983.             set(HTML_Gad,MUIA_Group_ActivePage,0);
  2984.             }
  2985.         else{
  2986. //            DoMethod(App,MUIM_Application_SetMenuState,mo_expand_images_current,FALSE);
  2987. //            DoMethod(App,MUIM_Application_SetMenuState,mo_delay_image_loads,FALSE);
  2988.             DoMethod(App,MUIM_Application_SetMenuState,mo_clear_image_cache,FALSE);
  2989.             DoMethod(App,MUIM_Application_SetMenuState,mo_isindex_to_form,FALSE);
  2990.  
  2991.             if(mui_version<11){
  2992.                 DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_text,FALSE);
  2993.                 DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_image,FALSE);
  2994.                 DoMethod(App,MUIM_Application_SetMenuState,mo_buttons_imagetext,FALSE);
  2995.                 }
  2996.             HTML_Data->have_forms=1;
  2997.             }
  2998.         if(mui_version<11){
  2999.             set(WI_Main, MUIA_Window_Open, TRUE); /* Open the window again */
  3000.             HTML_Data->have_formsI=0;
  3001.             set(WI_Wait, MUIA_Window_Open, FALSE); /* Hide info */
  3002. //            kprintf("Opening window.\n");
  3003.             }
  3004.         else
  3005.             DoMethod(HTML_Gad,MUIM_Group_ExitChange); /* All objects are added */
  3006.         HTML_Data->object_flags&=~Object_Changing;
  3007.         }
  3008.     else
  3009.         MUI_Redraw(HTML_Gad,MADF_DRAWOBJECT);
  3010.  
  3011.     if((mui_version<11) /* && HTML_Data->have_forms */){
  3012. /*        HTML_Data->scroll_y=HTML_Data->new_scroll_y; */
  3013.                 DoMethod(HTML_Gad,HTMLM_ResetAmigaGadgets);
  3014.         }
  3015.     }
  3016. }
  3017.  
  3018. void ClearWidget(FormPartInfo *fp)
  3019. {
  3020.     long n;
  3021.     switch(fp->Type){
  3022.         case FTYPE_TEXT:
  3023.         case FTYPE_PASSWORD:
  3024.             set((Object *)fp->UserData,MUIA_String_Contents,"");
  3025.             break;
  3026.         case FTYPE_TEXTAREA:
  3027.             set((Object *)fp->UserData,MUIA_TEF_Text,"");
  3028.             break;
  3029.         case FTYPE_CYCLE:
  3030.             set((Object *)fp->UserData,MUIA_Cycle_Active,0);
  3031.             break;
  3032.         case FTYPE_LISTV:
  3033.             DoMethod((Object *)fp->UserData,MUIM_List_Select,MUIV_List_Select_All,MUIV_List_Select_Off,NULL);
  3034.             break;
  3035.         case FTYPE_CHECKBOX:
  3036.             for(n=0;((WidgetInfo **)fp->UserData)[n];n++){
  3037.                 set((((WidgetInfo **)fp->UserData)[n])->MUI_SubObject,MUIA_Selected,0);
  3038.                 }
  3039.             break;
  3040.         case FTYPE_RADIO:
  3041.             for(n=0;((WidgetInfo **)fp->UserData)[n];n++){
  3042.                 set((((WidgetInfo **)fp->UserData)[n])->MUI_SubObject,MUIA_Selected,0);
  3043.                 }
  3044.             break;
  3045.         }
  3046. }
  3047.  
  3048. void ResetWidget(FormPartInfo *fp)
  3049. {
  3050.     long n;
  3051.     switch(fp->Type){
  3052.         case FTYPE_TEXT:
  3053.         case FTYPE_PASSWORD:
  3054.             set((Object *)fp->UserData,MUIA_String_Contents,fp->Widget->value);
  3055.             break;
  3056.         case FTYPE_TEXTAREA:
  3057.             set((Object *)fp->UserData,MUIA_TEF_Text,fp->Widget->value);
  3058.             break;
  3059.         case FTYPE_CYCLE:{
  3060.             char **cyclelist=(char **)fp->Widget->option;
  3061.             if(fp->Widget->value)
  3062.                 for(n=0;cyclelist[n];n++)
  3063.                     if(!stricmp(cyclelist[n],fp->Widget->value))
  3064.                         break;
  3065.             if(cyclelist[n])
  3066.                 set(fp->Widget->MUI_Object,MUIA_Cycle_Active,n);
  3067.             else
  3068.                 set((Object *)fp->UserData,MUIA_Cycle_Active,0);
  3069.             break;}
  3070.         case FTYPE_LISTV:{
  3071.             char **cyclelist=(char **)fp->Widget->option;
  3072.             char **selectedlist=(char **)fp->Widget->value;
  3073.             long i;
  3074.  
  3075.             DoMethod((Object *)fp->UserData,MUIM_List_Select,MUIV_List_Select_All,MUIV_List_Select_Off,NULL);
  3076.  
  3077.             for(i=0;cyclelist[i];i++)
  3078.                 for(n=0;selectedlist[n];n++)
  3079.                     if(!stricmp(cyclelist[i],selectedlist[n]))
  3080.                         DoMethod(fp->Widget->MUI_SubObject,MUIM_List_Select,i,MUIV_List_Select_On,NULL);
  3081.  
  3082.             break;}
  3083.         case FTYPE_CHECKBOX:
  3084.             for(n=0;((long **)fp->UserData)[n];n++){
  3085.                 set((((WidgetInfo **)fp->UserData)[n])->MUI_SubObject,MUIA_Selected,(((WidgetInfo **)fp->UserData)[n])->checked);
  3086.                 }
  3087.             break;
  3088.         case FTYPE_RADIO:
  3089.             for(n=0;((WidgetInfo **)fp->UserData)[n];n++){
  3090.                 set((((WidgetInfo **)fp->UserData)[n])->MUI_SubObject,MUIA_Selected,(((WidgetInfo **)fp->UserData)[n])->checked);
  3091.                 }
  3092.             break;
  3093.         }
  3094. }
  3095.  
  3096. static Object *ButtonPressed;
  3097.  
  3098. char *GetFormPartValue(FormPartInfo *fp,long *gadget)
  3099. {
  3100.     char *res;
  3101.     WidgetInfo *w;
  3102.     long i,t;
  3103.     BOOL found;
  3104.  
  3105.     switch(fp->Type){
  3106.         case FTYPE_BUTTON_S:
  3107.             if((fp->Widget->MUI_SubObject==ButtonPressed) && fp->Widget->name){
  3108.                 res=fp->Widget->value;
  3109.                 *gadget=-1;
  3110.                 }
  3111.             else
  3112.                 *gadget=-3;
  3113.             break;
  3114.         case FTYPE_TEXT:
  3115.         case FTYPE_PASSWORD:
  3116.             get((Object *)fp->UserData,MUIA_String_Contents,&res);
  3117.             *gadget=-1;
  3118.             break;
  3119.         case FTYPE_HIDDEN:
  3120.             res=((WidgetInfo *)fp->UserData)->value;
  3121.             *gadget=-1;
  3122.             break;
  3123.         case FTYPE_TEXTAREA:
  3124.             get((Object *)fp->UserData,MUIA_TEF_Text,&res);
  3125.             *gadget=-1;
  3126.             break;
  3127.         case FTYPE_CYCLE:
  3128.             get((Object *)fp->UserData,MUIA_Cycle_Active,&t);
  3129.             if(!(res=((char **)fp->Widget->returnv)[t]))
  3130.                 res=((char **)fp->Widget->option)[t];
  3131.             *gadget=-1;
  3132.             break;
  3133.         case FTYPE_LISTV:
  3134.             if(*gadget==-2)
  3135.                 t=MUIV_List_NextSelected_Start;
  3136.             else
  3137.                 t=*gadget;
  3138.  
  3139.             DoMethod(fp->Widget->MUI_SubObject,MUIM_List_NextSelected,&t);
  3140.             if (t!=MUIV_List_NextSelected_End)
  3141.                 if(!(res=((char **)fp->Widget->returnv)[t]))
  3142.                     res=((char **)fp->Widget->option)[t];
  3143.             *gadget=t;
  3144.             DoMethod(fp->Widget->MUI_SubObject,MUIM_List_NextSelected,&t);
  3145.             if(t==MUIV_List_NextSelected_End)
  3146.                 *gadget=-1;
  3147.  
  3148.             break;
  3149.         case FTYPE_CHECKBOX:
  3150.             found=FALSE;
  3151.             if(*gadget==-2)
  3152.                 *gadget=0;
  3153.             for(;((WidgetInfo **)fp->UserData)[*gadget];(*gadget)++){
  3154.                 w=((WidgetInfo **)fp->UserData)[*gadget];
  3155.                 get(w->MUI_SubObject,MUIA_Selected,&t);
  3156.                 if(t){
  3157.                     if(!found){
  3158.                         res=w->value;
  3159.                         found=TRUE;
  3160.                         }
  3161.                     else
  3162.                         break;
  3163.                     }
  3164.                 }
  3165.             if(!found)
  3166.                 *gadget=-3; /* Mark end of list */
  3167.             break;
  3168.         case FTYPE_RADIO:
  3169.             *gadget=-3; /* No new value found */
  3170.             for(i=0;((WidgetInfo **)fp->UserData)[i];i++){
  3171.                 w=((WidgetInfo **)fp->UserData)[i];
  3172.                 get(w->MUI_SubObject,MUIA_Selected,&t);
  3173.                 if(t){
  3174.                     res=w->value;
  3175.                     *gadget=-1; /* A value found */
  3176.                     break;
  3177.                     }
  3178.                 }
  3179.             break;
  3180.         default:
  3181.             *gadget=-3; /* No new value found */
  3182.             break;
  3183.         }
  3184.     return res;
  3185. }
  3186.  
  3187. BOOL CatFormPart(char *buffer,FormPartInfo *fp,long *i)
  3188. {
  3189.     long gadgets=-2; /* -3="no new value" -2="initial value" -1="This was the last value" */
  3190.     char *value,*c;
  3191.     BOOL success=0;
  3192.  
  3193.     while(gadgets!=-1 && gadgets!=-3){
  3194.         if (fp->Name){
  3195.             value =GetFormPartValue(fp,&gadgets);
  3196.             if(gadgets!=-3){
  3197.                 if(*i==-1 && (stricmp(fp->Name,"isindex")==0)){
  3198.                     if(value){
  3199.                         c = mo_escape_part (value);
  3200.                         strcat (buffer, c);
  3201.                         success=TRUE;
  3202.                         free (c);
  3203.                         }
  3204.                     }
  3205.                 else{
  3206.                     if(*i>0)
  3207.                         strcat(buffer,"&");
  3208.                     *i=1;
  3209.                     c = mo_escape_part (fp->Name);
  3210.                     strcat (buffer, c);
  3211.                     success=TRUE;
  3212.                     free (c);
  3213.         
  3214.                     strcat (buffer, "=");
  3215.                     if(value){
  3216.                         c = mo_escape_part (value);
  3217.                         strcat (buffer, c);
  3218.                         free (c);
  3219.                         }
  3220.                     }
  3221.                 }
  3222.         }
  3223.         else
  3224.             gadgets=-1;
  3225.     }
  3226.     return success;
  3227. }
  3228.  
  3229. long GetFormPartLength(FormPartInfo *fp)
  3230. {
  3231.     long gadgets=-2,length=0;
  3232.     char *value;
  3233.     /* Rack 'em up. */
  3234.  
  3235.     while(gadgets!=-1 && gadgets!=-3){
  3236.         if (fp->Name){
  3237.             value =GetFormPartValue(fp,&gadgets);
  3238.             if(gadgets!=-3){
  3239.                 if(gadgets!=0)
  3240.                     length++;
  3241.                 length+=strlen(fp->Name)+1;
  3242.                 if(value){
  3243.                     length+=strlen(value);
  3244.                     }
  3245.                 }
  3246.         }
  3247.         else
  3248.             gadgets=-1;
  3249.     }
  3250.     return length;
  3251. }
  3252.  
  3253. struct FormButtonHookMsg
  3254. {
  3255.     WidgetInfo *widget;
  3256.     FormInfo *Form;
  3257. };
  3258.  
  3259. BOOL GetFormQuery(FormInfo *Form,char **res,char **resurl)
  3260. {
  3261.     int do_post_urlencoded = 0;
  3262.     char *text;
  3263.     char *query;
  3264.     long len, i;
  3265.  
  3266.     WidgetInfo *cw;
  3267.     FormPartInfo *fp;
  3268.     LONG size;
  3269.     char *buf;
  3270.     char *url;
  3271.     char *method;
  3272.     BOOL success=0;
  3273.  
  3274.  
  3275.     /* Initial query: Breathing space. */
  3276.     len = 16;
  3277.     /* Add up lengths of strings. */
  3278.     for(fp=Form->FirstFormPart;fp;fp=fp->Next)
  3279.         len+=GetFormPartLength(fp)*3+2;
  3280.  
  3281.     /* Get the URL. */
  3282.     if (Form->href && *(Form->href))
  3283.         url = Form->href;
  3284.     else
  3285.         url = window.current_node->url;
  3286.  
  3287.     if (Form->method && *(Form->method))
  3288.         method = Form->method;
  3289.     else
  3290.         method = strdup ("GET");
  3291.  
  3292.     if (stricmp (method, "POST") == 0)
  3293.         do_post_urlencoded = 1;
  3294.  
  3295.     len += strlen (url);
  3296.  
  3297.     query = (char *)malloc (sizeof (char) * len);
  3298.  
  3299.  
  3300.     if (!do_post_urlencoded){
  3301.         strcpy (query, url);
  3302.         /* Clip out anchor. */
  3303.         strtok (query, "#");
  3304.         /* Clip out old query. */
  3305.         strtok (query, "?");
  3306.         if (query[strlen(query)-1] != '?'){
  3307.             strcat (query, "?");
  3308.             }
  3309.         }
  3310.     else query[0] = 0;
  3311.  
  3312.     for(fp=Form->FirstFormPart, i=0 ;fp;fp=fp->Next,i++)
  3313.         if(i==2) break; /* Check if it has more than one gadget */
  3314.  
  3315.     if(i>1) i=0; else i=-1;
  3316.     for(fp=Form->FirstFormPart;fp;fp=fp->Next)
  3317.         success|=CatFormPart(query,fp,&i);
  3318.  
  3319.     if(do_post_urlencoded) {
  3320.         *res=query;
  3321.         *resurl=url;
  3322.         }
  3323.     else {
  3324.         *res=NULL;
  3325.         *resurl=query;
  3326.         }
  3327.  
  3328.     return success;
  3329. }
  3330.  
  3331.  
  3332. void SubmitForm(struct FormButtonHookMsg *msg)
  3333. {
  3334.     char *query;
  3335.  
  3336.     char *url;
  3337.  
  3338.     GetFormQuery(msg->Form,&query,&url);
  3339.  
  3340.     if(url)
  3341.         if(!strnicmp("mailto:",url,7)){
  3342. #if DEBUG2==1
  3343.             kprintf("Mailto: isn't implemented YET\n");
  3344. #endif
  3345.             }
  3346.             
  3347.     if (query){
  3348. #if DEBUG2==1
  3349.         kprintf("URL: %s\nQuery: %s\n",url,query);
  3350. #endif
  3351.         SetAttrs(HTML_Gad,HTMLA_post_href,(ULONG)url,
  3352.                         HTMLA_post_text,(ULONG)query,TAG_DONE);
  3353.         }
  3354.     else{
  3355. #if DEBUG2==1
  3356.         kprintf("URL: %s\n",url);
  3357. #endif
  3358.         set(HTML_Gad,HTMLA_get_href,(ULONG)url);
  3359.         }
  3360. }
  3361.  
  3362. ULONG __saveds __asm FormButtonFunc(register __a0 struct Hook *hook,
  3363.                register __a2 APTR          object,
  3364.                register __a1 struct FormButtonHookMsg *msg)
  3365. {
  3366.     FormPartInfo *fp;
  3367.  
  3368.     if(msg->widget->type==FTYPE_BUTTON_S){
  3369.         ButtonPressed=object;
  3370.         SubmitForm(msg);
  3371.         }
  3372.     else if(msg->widget->type==FTYPE_BUTTON_R){
  3373.         for(fp=msg->Form->FirstFormPart;fp;fp=fp->Next)
  3374.             ResetWidget(fp);
  3375.         }
  3376.     else if(msg->widget->type==FTYPE_BUTTON_C){
  3377.         for(fp=msg->Form->FirstFormPart;fp;fp=fp->Next)
  3378.             ClearWidget(fp);
  3379.         }
  3380.     return 0;
  3381. }
  3382.  
  3383. ULONG __saveds __asm FormStringFunc(register __a0 struct Hook *hook,
  3384.                register __a2 APTR          object,
  3385.                register __a1 struct FormButtonHookMsg *msg)
  3386. {
  3387.     char *res;
  3388.     SubmitForm(msg);
  3389.     return 0;
  3390. }
  3391.  
  3392. struct Hook FormButton_hook=
  3393. {
  3394.     0,0,
  3395.     (APTR)FormButtonFunc,
  3396.     0,0
  3397. };
  3398.  
  3399. struct Hook FormString_hook=
  3400. {
  3401.     0,0,
  3402.     (APTR)FormStringFunc,
  3403.     0,0
  3404. };
  3405.  
  3406. void ImageSubmitForm(FormInfo *fptr,char *name,int x,int y)
  3407. {
  3408.     char *query,*newquery,*url;
  3409.     long len;
  3410.     long res;
  3411.     char valstr[10];
  3412.     res=GetFormQuery(fptr,&query,&url);
  3413.  
  3414.     if(query){
  3415.         len=strlen(query)+(name ? 2*strlen(name) : 0)+16; /* Coordinates larger than 6 diggits is _highly_ unlikely */
  3416.  
  3417.         newquery=malloc(len);
  3418.         strcpy(newquery,query);
  3419.         free(query);
  3420.  
  3421.         if(res)
  3422.             strcat(newquery,"&");
  3423.         if(name){
  3424.             strcat(newquery,name);
  3425.             strcat(newquery,".x=");
  3426.             }
  3427.         else
  3428.             strcat(newquery,"x=");
  3429.         sprintf(valstr, "%d&", x);
  3430.         strcat(newquery,valstr);
  3431.  
  3432.         if(name){
  3433.             strcat(newquery,name);
  3434.             strcat(newquery,".y=");
  3435.             }
  3436.         else
  3437.             strcat(newquery,"y=");
  3438.         sprintf(valstr, "%d", y);
  3439.         strcat(newquery,valstr);
  3440.  
  3441. #if DEBUG2==1
  3442.         kprintf("Query %s\n",newquery);
  3443. #endif
  3444.  
  3445.         SetAttrs(HTML_Gad,HTMLA_post_href,(ULONG)url,
  3446.                     HTMLA_post_text,(ULONG)newquery,TAG_DONE);
  3447.         }
  3448.     else{
  3449.         len=strlen(url)+(name ? 2*strlen(name) : 0)+16; /* Coordinates larger than 6 diggits is _highly_ unlikely */
  3450.  
  3451.         newquery=malloc(len);
  3452.         strcpy(newquery,url);
  3453.         free(url);
  3454.  
  3455.         if(res)
  3456.             strcat(newquery,"&");
  3457.         else
  3458.             strcat(newquery,"?");
  3459.  
  3460.         if(name){
  3461.             strcat(newquery,name);
  3462.             strcat(newquery,".x=");
  3463.             }
  3464.         else
  3465.             strcat(newquery,"x=");
  3466.         sprintf(valstr, "%d&", x);
  3467.         strcat(newquery,valstr);
  3468.  
  3469.         if(name){
  3470.             strcat(newquery,name);
  3471.             strcat(newquery,".y=");
  3472.             }
  3473.         else
  3474.             strcat(newquery,"y=");
  3475.         sprintf(valstr, "%d", y);
  3476.         strcat(newquery,valstr);
  3477.  
  3478. #if DEBUG2==1
  3479.         kprintf("Query %s\n",newquery);
  3480. #endif
  3481.  
  3482.         set(HTML_Gad,HTMLA_get_href,(ULONG)newquery);
  3483.         }
  3484. }
  3485.  
  3486.  
  3487.  
  3488. ULONG __saveds __asm FormRadioFunc(register __a0 struct Hook *hook,
  3489.                register __a2 APTR          object,
  3490.                register __a1 struct FormButtonHookMsg *msg)
  3491. {
  3492.     WidgetInfo *cw;
  3493.  
  3494.     for(cw=msg->widget->PrevRadio;cw;cw=cw->PrevRadio)
  3495.         set(cw->MUI_SubObject,MUIA_Selected,FALSE);
  3496.     for(cw=msg->widget->NextRadio;cw;cw=cw->NextRadio)
  3497.         set(cw->MUI_SubObject,MUIA_Selected,FALSE);
  3498.     return 0;
  3499. }
  3500.  
  3501. struct Hook FormRadio_hook=
  3502. {
  3503.     0,0,
  3504.     (APTR)FormRadioFunc,
  3505.     0,0
  3506. };
  3507.  
  3508. char *ComposeCommaList(char **values, int nof){
  3509.     long n,size=0,oldvalue;
  3510.     char **vt=values,*str;
  3511.     oldvalue=0;
  3512.     for(n=nof;n;n--){
  3513.         if(oldvalue) size++;
  3514.         if(*vt) size+=strlen(*vt++);
  3515.         else vt++;
  3516.         oldvalue=1;
  3517.         }
  3518.     str=malloc(size+1);
  3519.     *str=0x0;
  3520.     oldvalue=0;
  3521.     for(n=nof;n;n--){
  3522.         if(oldvalue) strcat(str,"|");
  3523.         if(*values) strcat(str,*values++);
  3524.         else values++;
  3525.         oldvalue=1;
  3526.         }
  3527.     return str;
  3528. }
  3529.  
  3530. struct TextEditHookMsg
  3531. {
  3532.     FormInfo *Form;
  3533. };
  3534.  
  3535. static ULONG __saveds __asm TextEditFunc(register __a0 struct Hook *hook,
  3536.                register __a2 APTR          obj,
  3537.                register __a1 struct TextEditHookMsg *msg)
  3538. {
  3539.     LONG res;
  3540.  
  3541.     get(obj,MUIA_TEF_Active,&res);
  3542.  
  3543.     if(res)
  3544.         set(HTML_Gad,HTMLA_ScrollKeys,FALSE);
  3545.     else
  3546.         set(HTML_Gad,HTMLA_ScrollKeys,TRUE);
  3547.     return 0;
  3548. }
  3549. struct Hook TextEdit_hook=
  3550. {
  3551.     0,0,
  3552.     (APTR)TextEditFunc,
  3553.     0,0
  3554. };
  3555.  
  3556. void FreeCommaList(char **values, int nof)
  3557. {
  3558.     for(;nof;nof--)
  3559.         if(*values)
  3560.             free(*values++);
  3561. }
  3562.  
  3563. /*
  3564. ** Custom layout function.
  3565. ** Perform several actions according to the messages lm_Type
  3566. ** field. Note that you must return MUILM_UNKNOWN if you do
  3567. ** not implement a specific lm_Type.
  3568. */
  3569.  
  3570. ULONG __saveds __asm LayoutFunc(register __a0 struct Hook *h,register __a2 Object *obj,register __a1 struct MUI_LayoutMsg *lm)
  3571. {
  3572.     HTMLGadClData *inst=INST_DATA(HTMLGadClass,HTML_Gad);
  3573.     switch (lm->lm_Type)
  3574.     {
  3575.  
  3576.         case MUILM_MINMAX:
  3577.         {
  3578. /*            /*
  3579.             ** MinMax calculation function. When this is called,
  3580.             ** the children of your group have already been asked
  3581.             ** about their min/max dimension so you can use their
  3582.             ** dimensions to calculate yours.
  3583.             **
  3584.             ** In this example, we make our minimum size twice as
  3585.             ** big as the biggest child in our group.
  3586.             */
  3587.  
  3588.             Object *cstate = (Object *)lm->lm_Children->mlh_Head;
  3589.             Object *child;
  3590.  
  3591.             WORD maxminwidth  = 0;
  3592.             WORD maxminheight = 0;
  3593.  
  3594.             /* find out biggest widths & heights of our children */
  3595.  
  3596.             while (child = NextObject(&cstate))
  3597.             {
  3598.                 if (maxminwidth <MUI_MAXMAX && _minwidth (child) > maxminwidth ) maxminwidth  = _minwidth (child);
  3599.                 if (maxminheight<MUI_MAXMAX && _minheight(child) > maxminheight) maxminheight = _minheight(child);
  3600.             }
  3601.  
  3602.             /* set the result fields in the message */
  3603. */
  3604.             lm->lm_MinMax.MinWidth  = 5000; /* Don't care since this */
  3605.             lm->lm_MinMax.MinHeight = 5000; /* is a virtual group */
  3606.             lm->lm_MinMax.DefWidth  = 5000;
  3607.             lm->lm_MinMax.DefHeight = 5000;
  3608.             lm->lm_MinMax.MaxWidth  = 5000;
  3609.             lm->lm_MinMax.MaxHeight = 5000;
  3610.  
  3611.             return(0);
  3612.         }
  3613.  
  3614.         case MUILM_LAYOUT:
  3615.         {
  3616.             Object *cstate,*child;
  3617.  
  3618.             /*
  3619.             ** Layout function. Here, we have to call MUI_Layout() for each
  3620.             ** our children. MUI wants us to place them in a rectangle
  3621.             ** defined by (0,0,lm->lm_Layout.Width-1,lm->lm_Layout.Height-1)
  3622.             ** You are free to put the children anywhere in this rectangle.
  3623.             **
  3624.             ** If you are a virtual group, you may also extend
  3625.             ** the given dimensions and place your children anywhere. Be sure
  3626.             ** to return the dimensions you need in lm->lm_Layout.Width and
  3627.             ** lm->lm_Layout.Height in this case.
  3628.             **
  3629.             ** Return TRUE if everything went ok, FALSE on error.
  3630.             ** Note: Errors during layout are not easy to handle for MUI.
  3631.             **       Better avoid them!
  3632.             */
  3633.  
  3634.  
  3635.             /* Reformat the text */
  3636.  
  3637.             inst->view_left = _mleft(HTML_Gad);
  3638.             inst->view_top = _mtop(HTML_Gad);
  3639.             inst->view_width = _mwidth(HTML_Gad);
  3640.             inst->view_height = _mheight(HTML_Gad);
  3641.             inst->rp=_rp(HTML_Gad);
  3642.             inst->win=_window(HTML_Gad);
  3643.  
  3644.  
  3645.             inst->object_flags|=Object_Reparsing;
  3646.             ReformatWindow(inst);
  3647.             inst->object_flags&=~Object_Reparsing;
  3648.  
  3649.             /* Place the objects */
  3650.  
  3651.             cstate = (Object *)lm->lm_Children->mlh_Head;
  3652.  
  3653.             while (child = NextObject(&cstate))
  3654.             {
  3655.                 if(child==G_Forms){ /* Place the main object upper left */
  3656.                     if(!MUI_Layout(child,0,0,_defwidth(child),_defwidth(child),0))
  3657.                         return(FALSE);
  3658.                     }
  3659.                 else
  3660.                     DoMethod(child,MUIM_NewGroup_Layout);
  3661.             }
  3662.  
  3663.             lm->lm_Layout.Width  = inst->doc_width;
  3664.             lm->lm_Layout.Height = inst->doc_height;
  3665.  
  3666.             return(TRUE);
  3667.         }
  3668.     }
  3669.     return(MUILM_UNKNOWN);
  3670. }
  3671. /*
  3672. Calling sequence when loading new page:
  3673.  
  3674. main.c calls gui-documents.c/mo_load_window_text (see below)
  3675. end
  3676.  
  3677. mo_load_window_text:
  3678. Calls: gui-documents.c/mo_do_window_text (see below) /* Hide, Parse and Reformat */
  3679. Calls: HTMLamiga.c/LoadInlinedImages
  3680. Calls: HTMLamiga.c/ResetAmigaGadgets
  3681. Redraws the HTML_Gad
  3682. end
  3683.  
  3684. mo_do_window_text:
  3685. Calls gui-documents.c/mo_set_text (see below)
  3686. end
  3687.  
  3688. mo_set_text:
  3689. Calls HTML.c/HTMLSetText (see below)
  3690. end
  3691.  
  3692. HTMLSetText
  3693. Calls HTMLamiga.c/HideWidgets
  3694. Calls HTMLamiga.c/HTMLParse
  3695. Calls HTML.c/ReformatWindow
  3696. end
  3697.  
  3698. mo_back_node:
  3699. Calls mo_set_win_current_node
  3700.  
  3701.  
  3702.  
  3703. */
  3704. /*
  3705. Check this URL!
  3706. http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/fill-out-forms/overview.html
  3707.  
  3708. http://www.phone.net/cgi-bin/index/ /* Mike Meyer home page */
  3709.  
  3710. http://web2.xerox.com/digitrad /* Isindex */
  3711.  
  3712. http://www.pdi.lodz.pl/~robert /* Escom news */
  3713.  
  3714. test case:
  3715. 1:    Ok
  3716. 2:    Ok
  3717. 3:    Ok
  3718. 4:    Ok
  3719. 5:    Ok
  3720. 6:    Ok
  3721. 7:    Ok
  3722. 8:    Ok
  3723. 9:    Ok
  3724. 10:    Ok
  3725. 11:    Ok
  3726. 12:    Ok
  3727. 13:    Ok
  3728.  
  3729. All in all:
  3730.  
  3731. Editing doesn't work.
  3732.  
  3733. */
  3734.